claude-launchpad 1.12.0 → 1.14.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.
Files changed (61) hide show
  1. package/README.md +11 -3
  2. package/dist/{chunk-DTCCQWOU.js → chunk-D6RAMWH6.js} +3 -3
  3. package/dist/{chunk-DTCCQWOU.js.map → chunk-D6RAMWH6.js.map} +1 -1
  4. package/dist/chunk-HSGSTSVN.js +212 -0
  5. package/dist/chunk-HSGSTSVN.js.map +1 -0
  6. package/dist/{chunk-DXDOVWOA.js → chunk-IDH3M4EI.js} +20 -232
  7. package/dist/chunk-IDH3M4EI.js.map +1 -0
  8. package/dist/{chunk-YZ53W47Z.js → chunk-IIWOSSL4.js} +2 -1
  9. package/dist/chunk-IIWOSSL4.js.map +1 -0
  10. package/dist/{chunk-ZLI4LI33.js → chunk-M6GVFN67.js} +2 -2
  11. package/dist/{chunk-F6SLV2FR.js → chunk-N2SCF7DB.js} +5 -6
  12. package/dist/chunk-N2SCF7DB.js.map +1 -0
  13. package/dist/chunk-OPORVSAF.js +225 -0
  14. package/dist/chunk-OPORVSAF.js.map +1 -0
  15. package/dist/{chunk-KPO4YURF.js → chunk-QEPE3WVF.js} +457 -85
  16. package/dist/chunk-QEPE3WVF.js.map +1 -0
  17. package/dist/chunk-UN43OVRW.js +184 -0
  18. package/dist/chunk-UN43OVRW.js.map +1 -0
  19. package/dist/{chunk-PH5OWJ42.js → chunk-VF7U63AI.js} +9 -5
  20. package/dist/{chunk-PH5OWJ42.js.map → chunk-VF7U63AI.js.map} +1 -1
  21. package/dist/cli.js +307 -87
  22. package/dist/cli.js.map +1 -1
  23. package/dist/commands/memory/server.js +48 -14
  24. package/dist/commands/memory/server.js.map +1 -1
  25. package/dist/{context-JALSYDYO.js → context-YIPO4LBS.js} +58 -55
  26. package/dist/context-YIPO4LBS.js.map +1 -0
  27. package/dist/doctor-DCHFJ3XV.js +108 -0
  28. package/dist/doctor-DCHFJ3XV.js.map +1 -0
  29. package/dist/{install-Q23F37GK.js → install-D32PV7SF.js} +12 -10
  30. package/dist/install-D32PV7SF.js.map +1 -0
  31. package/dist/{pull-FYKNNLYC.js → pull-YUQTDRUP.js} +17 -19
  32. package/dist/pull-YUQTDRUP.js.map +1 -0
  33. package/dist/{push-QSBK7BQU.js → push-U4IVTFOU.js} +13 -12
  34. package/dist/push-U4IVTFOU.js.map +1 -0
  35. package/dist/{require-deps-ZISUZLYD.js → require-deps-WDMHDGBN.js} +3 -3
  36. package/dist/{stats-SV53G6PQ.js → stats-77BYLKYP.js} +9 -7
  37. package/dist/{stats-SV53G6PQ.js.map → stats-77BYLKYP.js.map} +1 -1
  38. package/dist/{sync-2LDM44U4.js → sync-DTCWK2CY.js} +5 -5
  39. package/dist/{sync-clean-HQ523N7V.js → sync-clean-ACZCB3NZ.js} +4 -5
  40. package/dist/sync-clean-ACZCB3NZ.js.map +1 -0
  41. package/dist/{sync-status-V6WTI32X.js → sync-status-2V2RCYZO.js} +13 -12
  42. package/dist/sync-status-2V2RCYZO.js.map +1 -0
  43. package/dist/{tui-2UJ2OIHB.js → tui-HVJNLRY2.js} +11 -7
  44. package/dist/{tui-2UJ2OIHB.js.map → tui-HVJNLRY2.js.map} +1 -1
  45. package/package.json +27 -7
  46. package/scenarios/workflow/premature-victory.yaml +44 -0
  47. package/dist/chunk-DXDOVWOA.js.map +0 -1
  48. package/dist/chunk-F6SLV2FR.js.map +0 -1
  49. package/dist/chunk-KPO4YURF.js.map +0 -1
  50. package/dist/chunk-YZ53W47Z.js.map +0 -1
  51. package/dist/chunk-ZIG75MOB.js +0 -366
  52. package/dist/chunk-ZIG75MOB.js.map +0 -1
  53. package/dist/context-JALSYDYO.js.map +0 -1
  54. package/dist/install-Q23F37GK.js.map +0 -1
  55. package/dist/pull-FYKNNLYC.js.map +0 -1
  56. package/dist/push-QSBK7BQU.js.map +0 -1
  57. package/dist/sync-clean-HQ523N7V.js.map +0 -1
  58. package/dist/sync-status-V6WTI32X.js.map +0 -1
  59. /package/dist/{chunk-ZLI4LI33.js.map → chunk-M6GVFN67.js.map} +0 -0
  60. /package/dist/{require-deps-ZISUZLYD.js.map → require-deps-WDMHDGBN.js.map} +0 -0
  61. /package/dist/{sync-2LDM44U4.js.map → sync-DTCWK2CY.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/fs-utils.ts","../src/lib/settings.ts","../src/lib/output.ts","../src/commands/doctor/fixer.ts","../src/lib/sections.ts","../src/lib/detect.ts","../src/commands/init/generators/claudeignore.ts","../src/commands/init/generators/skill-enhance.ts","../src/commands/init/generators/backlog.ts","../src/lib/memory-placement.ts","../src/lib/stub-marker.ts","../src/commands/doctor/fixer-sprint.ts","../src/lib/hook-builder.ts","../src/lib/hook-scripts.ts","../src/lib/hook-input.ts","../src/commands/doctor/fixer-quality.ts","../src/commands/init/generators/workflow-rule.ts","../src/commands/init/generators/hooks-rule.ts","../src/commands/init/generators/verification-rule.ts","../src/commands/init/generators/agent-reviewer.ts","../src/commands/doctor/fixer-hooks.ts","../src/commands/doctor/fixer-hook-input.ts","../src/commands/doctor/fixer-memory.ts"],"sourcesContent":["import { readFile, access } from \"node:fs/promises\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readFileOrNull(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nexport async function readJsonOrNull<T>(path: string): Promise<T | null> {\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { log } from \"./output.js\";\n\nasync function readJsonFile(path: string): Promise<Record<string, unknown> | null> {\n let raw: string;\n try {\n raw = await readFile(path, \"utf-8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return {};\n log.warnOnce(`read:${path}`, `Could not read ${path}: ${(err as Error).message}`);\n return null;\n }\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n log.warnOnce(`parse:${path}`, `${path} is not valid JSON: ${(err as Error).message}. Treating as unreadable to avoid clobbering it.`);\n return null;\n }\n}\n\nexport async function readSettingsJson(root: string): Promise<Record<string, unknown> | null> {\n return readJsonFile(join(root, \".claude\", \"settings.json\"));\n}\n\nexport async function writeSettingsJson(root: string, settings: Record<string, unknown>): Promise<void> {\n const dir = join(root, \".claude\");\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, \"settings.json\"), JSON.stringify(settings, null, 2) + \"\\n\");\n}\n\nexport async function readSettingsLocalJson(root: string): Promise<Record<string, unknown> | null> {\n return readJsonFile(join(root, \".claude\", \"settings.local.json\"));\n}\n\nexport async function writeSettingsLocalJson(root: string, settings: Record<string, unknown>): Promise<void> {\n const dir = join(root, \".claude\");\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, \"settings.local.json\"), JSON.stringify(settings, null, 2) + \"\\n\");\n}\n","import chalk from \"chalk\";\nimport type { Severity, AnalyzerResult, DiagnosticIssue } from \"../types/index.js\";\nimport { hasAutoFix } from \"../commands/doctor/fixer.js\";\n\n// ─── Colors ───\n\nexport const colors = {\n success: chalk.green,\n error: chalk.red,\n warn: chalk.yellow,\n info: chalk.cyan,\n dim: chalk.dim,\n bold: chalk.bold,\n score: (score: number): string => {\n if (score >= 80) return chalk.green.bold(`${score}%`);\n if (score >= 60) return chalk.yellow.bold(`${score}%`);\n return chalk.red.bold(`${score}%`);\n },\n severity: (sev: Severity): string => {\n const map: Record<Severity, (s: string) => string> = {\n critical: chalk.bgRed.white.bold,\n high: chalk.red.bold,\n medium: chalk.yellow,\n low: chalk.cyan,\n info: chalk.dim,\n };\n return map[sev](` ${sev.toUpperCase()} `);\n },\n} as const;\n\n// ─── Prefixed Output ───\n\nconst warnedKeys = new Set<string>();\n\nexport const log = {\n success: (msg: string): void => console.log(` ${chalk.green(\"✓\")} ${msg}`),\n error: (msg: string): void => console.log(` ${chalk.red(\"✗\")} ${msg}`),\n warn: (msg: string): void => console.log(` ${chalk.yellow(\"!\")} ${msg}`),\n warnOnce: (key: string, msg: string): void => {\n if (warnedKeys.has(key)) return;\n warnedKeys.add(key);\n console.log(` ${chalk.yellow(\"!\")} ${msg}`);\n },\n step: (msg: string): void => console.log(` ${chalk.cyan(\"→\")} ${msg}`),\n info: (msg: string): void => console.log(` ${chalk.dim(\"·\")} ${msg}`),\n blank: (): void => console.log(),\n} as const;\n\n// ─── Banner ───\n\nexport function printBanner(): void {\n log.blank();\n console.log(chalk.cyan.bold(\" Claude Launchpad\"));\n console.log(chalk.dim(\" Scaffold · Diagnose · Evaluate · Remember\"));\n log.blank();\n}\n\n// ─── Score Display ───\n\nexport function printScoreCard(label: string, score: number, max: number = 100): void {\n const pct = Math.round((score / max) * 100);\n const bar = renderBar(pct, 20);\n console.log(` ${chalk.bold(label.padEnd(22))} ${bar} ${colors.score(pct).padStart(12)}`);\n}\n\nfunction renderBar(pct: number, width: number): string {\n const filled = Math.round((pct / 100) * width);\n const empty = width - filled;\n const color = pct >= 80 ? chalk.green : pct >= 60 ? chalk.yellow : chalk.red;\n return color(\"━\".repeat(filled)) + chalk.dim(\"─\".repeat(empty));\n}\n\n// ─── Issues List (replaces table) ───\n\nexport function printIssue(severity: Severity, _analyzer: string, message: string): void {\n const sevLabel: Record<Severity, string> = {\n critical: chalk.bgRed.white.bold(\" CRIT \"),\n high: chalk.red.bold(\"HIGH\"),\n medium: chalk.yellow(\"MED \"),\n low: chalk.dim(\"LOW \"),\n info: chalk.dim(\"INFO\"),\n };\n console.log(` ${sevLabel[severity]} ${message}`);\n}\n\n// ─── Report Rendering (shared by doctor + watcher) ───\n\nexport function renderDoctorReport(results: ReadonlyArray<AnalyzerResult>, options?: { afterFix?: boolean }): {\n overallScore: number;\n actionableCount: number;\n} {\n const overallScore = Math.round(\n results.reduce((sum, r) => sum + r.score, 0) / results.length,\n );\n\n for (const result of results) {\n printScoreCard(result.name, result.score);\n }\n log.blank();\n printScoreCard(\"Overall\", overallScore);\n log.blank();\n\n const allIssues = results.flatMap((r) => r.issues);\n const actionable = allIssues.filter((i) => i.severity !== \"info\");\n\n if (actionable.length === 0) {\n log.success(\"No issues found. Your configuration looks solid.\");\n return { overallScore, actionableCount: 0 };\n }\n\n const sorted = [...actionable].sort((a, b) => {\n const order: Record<string, number> = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };\n return (order[a.severity] ?? 4) - (order[b.severity] ?? 4);\n });\n\n for (const issue of sorted) {\n printIssue(issue.severity, issue.analyzer, issue.message);\n }\n\n log.blank();\n if (options?.afterFix) {\n log.info(`${actionable.length} remaining issue(s) require manual intervention.`);\n } else {\n const fixable = actionable.filter((i) => hasAutoFix(i));\n if (fixable.length > 0) {\n log.info(`${actionable.length} issue(s). Run ${chalk.bold(\"--fix\")} to auto-repair or ${chalk.bold(\"--fix --dry-run\")} to preview.`);\n } else {\n log.info(`${actionable.length} issue(s) require manual intervention.`);\n }\n }\n return { overallScore, actionableCount: actionable.length };\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { log } from \"../../lib/output.js\";\nimport {\n SESSION_START_CONTENT,\n BACKLOG_CONTENT,\n STOP_AND_SWARM_CONTENT,\n OFF_LIMITS_CONTENT,\n SKILL_AUTHORING_CONTENT,\n} from \"../../lib/sections.js\";\nimport { fileExists } from \"../../lib/fs-utils.js\";\nimport { detectProject } from \"../../lib/detect.js\";\nimport { generateClaudeignore } from \"../init/generators/claudeignore.js\";\nimport { generateEnhanceSkill } from \"../init/generators/skill-enhance.js\";\nimport { generateBacklogMd } from \"../init/generators/backlog.js\";\nimport { readSettingsJson, writeSettingsJson } from \"../../lib/settings.js\";\nimport { getMemoryPlacement } from \"../../lib/memory-placement.js\";\nimport { wrapStub } from \"../../lib/stub-marker.js\";\nimport {\n createWorktreeInclude,\n addSprintSizeHook,\n addSprintOpenHook,\n addSprintCompleteNudge,\n addWorkflowCheckHook,\n migrateSprintOpenHookEvent,\n upgradeStaleNudge,\n refreshHygieneScripts,\n} from \"./fixer-sprint.js\";\nimport {\n createWorkflowRule,\n createHooksRule,\n createVerificationRule,\n collapseMemoryHeadings,\n updateWorkflowRule,\n updateVerificationRule,\n fixStaleSwarmPhrase,\n createReviewerAgent,\n} from \"./fixer-quality.js\";\nimport {\n addEnvProtectionHook,\n addAutoFormatHook,\n addForcePushProtection,\n migratePostCompactHook,\n addCompactMatcherHook,\n addSessionStartHook,\n} from \"./fixer-hooks.js\";\nimport { rewriteEnvVarHooks } from \"./fixer-hook-input.js\";\nimport {\n upgradeBareMemoryHooks,\n disableAutoMemory,\n addMemoryToolPermissions,\n addAllowedMcpServers,\n addMemoryToAllowedMcpServers,\n addSessionStartPullHook,\n addSessionEndPushHook,\n upgradeStaleSessionEndPushHook,\n removeStaleStopHook,\n} from \"./fixer-memory.js\";\nimport type {\n DiagnosticIssue,\n DetectedProject,\n MemoryPlacement,\n} from \"../../types/index.js\";\n\ninterface FixResult {\n readonly fixed: number;\n readonly skipped: number;\n}\n\n/**\n * Auto-apply deterministic fixes for doctor issues.\n * Only applies fixes that are safe and unambiguous.\n */\nexport async function applyFixes(\n issues: ReadonlyArray<DiagnosticIssue>,\n projectRoot: string,\n): Promise<FixResult> {\n const detected = await detectProject(projectRoot);\n const hasMemoryIssues = issues.some((i) => i.analyzer === \"Memory\");\n const placement = hasMemoryIssues\n ? await getMemoryPlacement(projectRoot)\n : \"shared\";\n let fixed = 0;\n let skipped = 0;\n\n for (const issue of issues) {\n const applied = await tryFix(issue, projectRoot, detected, placement);\n if (applied) {\n fixed++;\n } else {\n skipped++;\n }\n }\n\n return { fixed, skipped };\n}\n\n// Fix lookup table: [analyzer, message substring] → fix function\ntype FixFn = (\n root: string,\n detected: DetectedProject,\n placement: MemoryPlacement,\n) => Promise<boolean>;\n\nconst FIX_TABLE: ReadonlyArray<{\n analyzer: string;\n match: string;\n fix: FixFn;\n}> = [\n {\n analyzer: \"Hooks\",\n match: \"$TOOL_INPUT_* env var\",\n fix: (root) => rewriteEnvVarHooks(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"No hooks configured\",\n fix: async (root, detected) => {\n const a = await addEnvProtectionHook(root);\n const b = await addAutoFormatHook(root, detected);\n const c = await addForcePushProtection(root);\n const d = await addSessionStartHook(root);\n return a || b || c || d;\n },\n },\n {\n analyzer: \"Hooks\",\n match: \".env file protection\",\n fix: (root) => addEnvProtectionHook(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"auto-format\",\n fix: (root, detected) => addAutoFormatHook(root, detected),\n },\n {\n analyzer: \"Hooks\",\n match: \"No PreToolUse\",\n fix: (root) => addEnvProtectionHook(root),\n },\n {\n analyzer: \"Quality\",\n match: \"Architecture\",\n fix: (root) =>\n addClaudeMdSection(\n root,\n \"## Architecture\",\n wrapStub(\n \"<!-- TODO: Describe your codebase structure. Run `/lp-enhance` to auto-fill this. -->\",\n ),\n ),\n },\n {\n analyzer: \"Quality\",\n match: \"Off-Limits\",\n fix: (root) =>\n addClaudeMdSection(root, \"## Off-Limits\", wrapStub(OFF_LIMITS_CONTENT)),\n },\n {\n analyzer: \"Quality\",\n match: \"Commands\",\n fix: (root) =>\n addClaudeMdSection(\n root,\n \"## Commands\",\n wrapStub(\"<!-- TODO: Add your dev/build/test commands -->\"),\n ),\n },\n {\n analyzer: \"Quality\",\n match: \"Stack\",\n fix: (root, detected) => {\n // Detected stack is real content; TODO fallback is a stub.\n if (detected.language) {\n const content = `- **Language**: ${detected.language}${detected.framework ? `\\n- **Framework**: ${detected.framework}` : \"\"}${detected.packageManager ? `\\n- **Package Manager**: ${detected.packageManager}` : \"\"}`;\n return addClaudeMdSection(root, \"## Stack\", content);\n }\n return addClaudeMdSection(\n root,\n \"## Stack\",\n wrapStub(\"<!-- TODO: Define your tech stack -->\"),\n );\n },\n },\n {\n analyzer: \"Quality\",\n match: \"Session Start\",\n fix: (root) =>\n addClaudeMdSection(\n root,\n \"## Session Start\",\n wrapStub(SESSION_START_CONTENT),\n ),\n },\n {\n analyzer: \"Quality\",\n match: \"Backlog\",\n fix: (root) =>\n addClaudeMdSection(root, \"## Backlog\", wrapStub(BACKLOG_CONTENT)),\n },\n {\n analyzer: \"Quality\",\n match: \"Stop-and-Swarm section is outdated\",\n fix: (root) => fixStaleSwarmPhrase(root),\n },\n {\n analyzer: \"Quality\",\n match: \"Stop-and-Swarm\",\n fix: (root) =>\n addClaudeMdSection(\n root,\n \"## Stop-and-Swarm\",\n wrapStub(STOP_AND_SWARM_CONTENT),\n ),\n },\n {\n analyzer: \"Rules\",\n match: \"workflow.md rule is outdated\",\n fix: (root) => updateWorkflowRule(root),\n },\n {\n analyzer: \"Rules\",\n match: \"verification.md rule is outdated\",\n fix: (root) => updateVerificationRule(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No .claude/agents/code-reviewer.md\",\n fix: (root) => createReviewerAgent(root),\n },\n {\n analyzer: \"Quality\",\n match: \"Duplicate ## Memory\",\n fix: (root) => collapseMemoryHeadings(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No BACKLOG.md\",\n fix: (root) => createBacklogMd(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No .claudeignore\",\n fix: (root, detected) => createClaudeignore(root, detected),\n },\n {\n analyzer: \"Rules\",\n match: \"No .claude/rules/workflow.md\",\n fix: (root) => createWorkflowRule(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No .claude/rules/hooks.md\",\n fix: (root) => createHooksRule(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No .claude/rules/verification.md\",\n fix: (root) => createVerificationRule(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No .claude/rules/\",\n fix: (root) => createStarterRules(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"PostCompact hooks can't inject context\",\n fix: (root) => migratePostCompactHook(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"compact matcher\",\n fix: (root) => addCompactMatcherHook(root),\n },\n {\n analyzer: \"Permissions\",\n match: \"force-push\",\n fix: (root) => addForcePushProtection(root),\n },\n {\n analyzer: \"Permissions\",\n match: \"Credential files not blocked\",\n fix: (root) => addCredentialDenyRules(root),\n },\n {\n analyzer: \"Permissions\",\n match: \"Bypass permissions mode\",\n fix: (root) => addBypassDisable(root),\n },\n {\n analyzer: \"Permissions\",\n match: \"Sandbox lacks a write grant\",\n fix: (root) => addSandboxMemoryWriteGrant(root),\n },\n {\n analyzer: \"Permissions\",\n match: \".env is protected by hooks but not in .claudeignore\",\n fix: (root) => addEnvToClaudeignore(root),\n },\n {\n analyzer: \"Permissions\",\n match: \".worktreeinclude is missing or empty\",\n fix: (root) => createWorktreeInclude(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"registered on PreToolUse\",\n fix: (root) => migrateSprintOpenHookEvent(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"nudge uses bare stdout\",\n fix: (root) => upgradeStaleNudge(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"Outdated hygiene script\",\n fix: (root) => refreshHygieneScripts(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"sprint-size-check\",\n fix: (root) => addSprintSizeHook(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"sprint-open-check\",\n fix: (root) => addSprintOpenHook(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"sprint-complete nudge\",\n fix: (root) => addSprintCompleteNudge(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"workflow-check.sh\",\n fix: (root) => addWorkflowCheckHook(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No skill authoring conventions\",\n fix: (root) => addSkillAuthoringConventions(root),\n },\n {\n analyzer: \"Rules\",\n match: \"No /lp-enhance skill\",\n fix: (root) => createEnhanceSkill(root),\n },\n {\n analyzer: \"Rules\",\n match: \"lp-enhance skill is outdated\",\n fix: (root) => updateEnhanceSkill(root),\n },\n {\n analyzer: \"Settings\",\n match: \"Deprecated includeCoAuthoredBy\",\n fix: (root) => migrateAttribution(root),\n },\n {\n analyzer: \"Hooks\",\n match: \"SessionStart\",\n fix: (root) => addSessionStartHook(root),\n },\n {\n analyzer: \"Memory\",\n match: \"bare claude-launchpad binary\",\n fix: (root) => upgradeBareMemoryHooks(root),\n },\n {\n analyzer: \"Memory\",\n match: \"Deprecated Stop hook\",\n fix: (root) => removeStaleStopHook(root),\n },\n {\n analyzer: \"Memory\",\n match: \"autoMemoryEnabled not disabled\",\n fix: (root, _det, placement) => disableAutoMemory(root, placement),\n },\n {\n analyzer: \"Memory\",\n match: \"MCP tool permission\",\n fix: (root, _det, placement) => addMemoryToolPermissions(root, placement),\n },\n {\n analyzer: \"MCP\",\n match: \"no allowedMcpServers\",\n fix: (root, _det, placement) => addAllowedMcpServers(root, placement),\n },\n {\n analyzer: \"Memory\",\n match: \"allowedMcpServers is set but does not include agentic-memory\",\n fix: (root) => addMemoryToAllowedMcpServers(root),\n },\n {\n analyzer: \"Memory\",\n match: \"SessionStart hook to auto-pull\",\n fix: (root, _det, placement) => addSessionStartPullHook(root, placement),\n },\n {\n analyzer: \"Memory\",\n match: \"SessionEnd hook to auto-push\",\n fix: (root, _det, placement) => addSessionEndPushHook(root, placement),\n },\n {\n analyzer: \"Memory\",\n match: \"SessionEnd push hook is not nohup-wrapped\",\n fix: (root) => upgradeStaleSessionEndPushHook(root),\n },\n {\n analyzer: \"Memory\",\n match: \"CLAUDE.md missing memory guidance\",\n fix: (root, _det, placement) => {\n const content =\n \"Use agentic-memory to persist knowledge across sessions:\\n- Memories are automatically injected at session start\\n- STORE IMMEDIATELY when: a dependency strategy changes, an architecture decision is made, a convention is established, a bug pattern is discovered, or a feature is killed/added\\n- Use memory_search before memory_store to check for duplicates\\n- NEVER store credentials, API keys, tokens, or secrets in memories\";\n const target =\n placement === \"local\" ? join(root, \".claude\", \"CLAUDE.md\") : undefined;\n return addClaudeMdSection(root, \"## Memory\", wrapStub(content), target);\n },\n },\n];\n\nexport function hasAutoFix(issue: DiagnosticIssue): boolean {\n return FIX_TABLE.some(\n (e) => e.analyzer === issue.analyzer && issue.message.includes(e.match),\n );\n}\n\nasync function tryFix(\n issue: DiagnosticIssue,\n root: string,\n detected: DetectedProject,\n placement: MemoryPlacement,\n): Promise<boolean> {\n const entry = FIX_TABLE.find(\n (e) => e.analyzer === issue.analyzer && issue.message.includes(e.match),\n );\n return entry ? entry.fix(root, detected, placement) : false;\n}\n\n// ─── Fix Implementations ───\n\nasync function migrateAttribution(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n if (settings.includeCoAuthoredBy === undefined) return false;\n\n const { includeCoAuthoredBy: _, ...rest } = settings;\n const updated = { ...rest, attribution: { commit: \"\", pr: \"\" } };\n await writeSettingsJson(root, updated);\n log.success(\"Migrated includeCoAuthoredBy → attribution object\");\n return true;\n}\n\nasync function addCredentialDenyRules(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const permissions = (settings.permissions ?? {}) as Record<string, unknown>;\n const deny = (permissions.deny as string[] | undefined) ?? [];\n\n const toAdd = [\"Read(~/.ssh/*)\", \"Read(~/.aws/*)\", \"Read(~/.npmrc)\"];\n const missing = toAdd.filter((p) => !deny.includes(p));\n if (missing.length === 0) return false;\n\n const updated = {\n ...settings,\n permissions: { ...permissions, deny: [...deny, ...missing] },\n };\n await writeSettingsJson(root, updated);\n log.success(\"Added credential deny rules (SSH, AWS, npm)\");\n return true;\n}\n\nasync function addBypassDisable(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n if (settings.disableBypassPermissionsMode === \"disable\") return false;\n\n const updated = { ...settings, disableBypassPermissionsMode: \"disable\" };\n await writeSettingsJson(root, updated);\n log.success(\"Added disableBypassPermissionsMode: disable\");\n return true;\n}\n\n/**\n * Grant Bash-run memory commands write access to ~/.agentic-memory while\n * keeping the sandbox enabled. Never removes or weakens the sandbox itself.\n */\nasync function addSandboxMemoryWriteGrant(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const sandbox = settings.sandbox as Record<string, unknown> | undefined;\n if (sandbox === undefined) return false;\n\n const filesystem = (sandbox.filesystem ?? {}) as Record<string, unknown>;\n const allowWrite = (filesystem.allowWrite as string[] | undefined) ?? [];\n if (allowWrite.some((p) => p.includes(\".agentic-memory\"))) return false;\n\n const updated = {\n ...settings,\n sandbox: {\n ...sandbox,\n filesystem: {\n ...filesystem,\n allowWrite: [...allowWrite, \"~/.agentic-memory\"],\n },\n },\n };\n await writeSettingsJson(root, updated);\n log.success(\n \"Added ~/.agentic-memory to sandbox.filesystem.allowWrite (sandbox stays enabled)\",\n );\n return true;\n}\n\nasync function addEnvToClaudeignore(root: string): Promise<boolean> {\n const ignorePath = join(root, \".claudeignore\");\n let content: string;\n try {\n content = await readFile(ignorePath, \"utf-8\");\n } catch {\n return false; // No .claudeignore to modify\n }\n\n const lines = content.split(\"\\n\").map((l) => l.trim());\n if (lines.some((l) => l === \".env\" || l === \".env.*\" || l === \".env*\"))\n return false;\n\n await writeFile(ignorePath, content.trimEnd() + \"\\n.env\\n.env.*\\n\");\n log.success(\"Added .env to .claudeignore\");\n return true;\n}\n\nasync function addClaudeMdSection(\n root: string,\n heading: string,\n content: string,\n targetPath?: string,\n): Promise<boolean> {\n const claudeMdPath = targetPath ?? join(root, \"CLAUDE.md\");\n let existing: string;\n try {\n existing = await readFile(claudeMdPath, \"utf-8\");\n } catch {\n if (!targetPath) return false; // No root CLAUDE.md to add to\n // Create local .claude/CLAUDE.md\n await mkdir(join(root, \".claude\"), { recursive: true });\n existing = \"# Local Claude Config\\n\";\n }\n\n // Don't add if section already exists\n if (existing.includes(heading)) return false;\n\n // Append before Key Decisions if it exists, otherwise at end\n const keyDecisionsIdx = existing.indexOf(\"## Key Decisions\");\n const insertAt = keyDecisionsIdx > -1 ? keyDecisionsIdx : existing.length;\n\n const section = `\\n${heading}\\n${content}\\n\\n`;\n const updated =\n existing.slice(0, insertAt) + section + existing.slice(insertAt);\n\n await writeFile(claudeMdPath, updated);\n const label = targetPath ? \".claude/CLAUDE.md\" : \"CLAUDE.md\";\n log.success(`Added \"${heading}\" section to ${label}`);\n return true;\n}\n\nasync function createBacklogMd(root: string): Promise<boolean> {\n const backlogPath = join(root, \"BACKLOG.md\");\n if (await fileExists(backlogPath)) return false;\n\n const name = root.split(\"/\").pop() ?? \"Project\";\n await writeFile(backlogPath, generateBacklogMd({ name, description: \"\" }));\n log.success(\n \"Generated BACKLOG.md (WP template + P0–P3 sections + changelog)\",\n );\n return true;\n}\n\nasync function createClaudeignore(\n root: string,\n detected: DetectedProject,\n): Promise<boolean> {\n const ignorePath = join(root, \".claudeignore\");\n if (await fileExists(ignorePath)) return false;\n\n const content = generateClaudeignore(detected);\n await writeFile(ignorePath, content);\n log.success(\"Generated .claudeignore with language-specific ignore patterns\");\n return true;\n}\n\nconst SKILL_AUTHORING_SECTION = `\\n## Skill Authoring\\n\\n${SKILL_AUTHORING_CONTENT}\\n`;\n\nasync function createStarterRules(root: string): Promise<boolean> {\n const rulesDir = join(root, \".claude\", \"rules\");\n if (await fileExists(rulesDir)) return false;\n\n await mkdir(rulesDir, { recursive: true });\n\n await writeFile(\n join(rulesDir, \"conventions.md\"),\n `# Project Conventions\n\n- Use conventional commits (feat:, fix:, docs:, refactor:, test:, chore:)\n- Keep files under 400 lines, functions under 50 lines\n- Handle errors explicitly — no empty catch blocks\n- Validate input at system boundaries\n${SKILL_AUTHORING_SECTION}`,\n );\n\n log.success(\"Created .claude/rules/conventions.md with starter rules\");\n return true;\n}\n\nasync function addSkillAuthoringConventions(root: string): Promise<boolean> {\n const conventionsPath = join(root, \".claude\", \"rules\", \"conventions.md\");\n let content: string;\n try {\n content = await readFile(conventionsPath, \"utf-8\");\n } catch {\n // No conventions.md — createStarterRules will handle it\n return false;\n }\n\n if (/^##\\s+Skill\\s+Authoring/im.test(content)) return false;\n\n await writeFile(\n conventionsPath,\n content.trimEnd() + \"\\n\" + SKILL_AUTHORING_SECTION,\n );\n log.success(\"Added Skill Authoring section to .claude/rules/conventions.md\");\n return true;\n}\n\nasync function createEnhanceSkill(root: string): Promise<boolean> {\n const skillDir = join(root, \".claude\", \"skills\", \"lp-enhance\");\n const skillPath = join(skillDir, \"SKILL.md\");\n const globalPath = join(\n homedir(),\n \".claude\",\n \"skills\",\n \"lp-enhance\",\n \"SKILL.md\",\n );\n // Also check legacy commands/ location\n const legacyProject = join(root, \".claude\", \"commands\", \"lp-enhance.md\");\n const legacyGlobal = join(homedir(), \".claude\", \"commands\", \"lp-enhance.md\");\n\n if (\n (await fileExists(skillPath)) ||\n (await fileExists(globalPath)) ||\n (await fileExists(legacyProject)) ||\n (await fileExists(legacyGlobal))\n )\n return false;\n\n await mkdir(skillDir, { recursive: true });\n await writeFile(skillPath, generateEnhanceSkill());\n log.success(\"Generated /lp-enhance skill (.claude/skills/lp-enhance/)\");\n return true;\n}\n\nasync function updateEnhanceSkill(root: string): Promise<boolean> {\n // Update whichever location has the skill installed\n const projectPath = join(root, \".claude\", \"skills\", \"lp-enhance\", \"SKILL.md\");\n const globalPath = join(\n homedir(),\n \".claude\",\n \"skills\",\n \"lp-enhance\",\n \"SKILL.md\",\n );\n\n const targetPath = (await fileExists(projectPath))\n ? projectPath\n : (await fileExists(globalPath))\n ? globalPath\n : null;\n\n if (!targetPath) return false;\n\n await writeFile(targetPath, generateEnhanceSkill());\n log.success(\"Updated /lp-enhance skill to latest version\");\n return true;\n}\n","/**\n * Shared CLAUDE.md section content used by both init generators and doctor fixer.\n * Single source of truth — prevents drift between init and --fix.\n */\n\nexport const SESSION_START_CONTENT =\n \"- ALWAYS read @TASKS.md first — it tracks progress across sessions\\n\" +\n \"- Check the Session Log at the bottom of TASKS.md for where we left off\\n\" +\n \"- Update TASKS.md as you complete work\";\n\nexport const BACKLOG_CONTENT =\n \"- When a feature is discussed but deferred, add it to BACKLOG.md immediately\\n\" +\n \"- Never leave future ideas only in TASKS.md or conversation — they get lost\\n\" +\n \"- BACKLOG.md is the single source of truth for parked features\\n\" +\n \"- Every WP uses the 7-field template in BACKLOG.md — no freeform entries\\n\" +\n \"- Pull a WP into a sprint = **move**, not copy. A WP lives in exactly one file at a time\";\n\nexport const STOP_AND_SWARM_CONTENT =\n \"Three failed iterations on the same problem = stop iterating alone.\\n\" +\n \"(An iteration = an attempted fix that did not change the failing symptom. Announce \\\"Attempt N\\\" when retrying so the count stays visible.)\\n\" +\n \"First, one systematic pass — it usually resolves the loop without the swarm:\\n\" +\n \"reproduce the failure, read the FULL error output, state one hypothesis about the root cause, and verify it BEFORE writing any fix.\\n\" +\n \"Only if that pass fails, swarm: dispatch at least 3 parallel subagents via the Task tool — in a single message so they run concurrently — each investigating from a different angle:\\n\" +\n \"1. Root-cause debug agent\\n\" +\n \"2. Upstream library/docs research agent\\n\" +\n \"3. Alternative architecture agent\\n\" +\n \"Hand each agent the exact repro command, the full error text, and the list of already-failed fixes — subagents start with empty context.\\n\" +\n \"Wait for all agents to return, synthesize their findings, then act.\\n\" +\n \"For re-planning after repeated failure, switch to plan mode instead of attempting again.\";\n\n/** The exact phrase shipped by pre-v1.12 templates — doctor flags and rewrites it. */\nexport const STALE_SWARM_PHRASE = \"spin up at least 3 parallel agents via the Agent tool\";\nexport const SWARM_PHRASE_REPLACEMENT = \"dispatch at least 3 parallel subagents via the Task tool (in a single message so they run concurrently)\";\n\nexport const OFF_LIMITS_CONTENT =\n \"- Never hardcode secrets — use environment variables\\n\" +\n \"- Never write to `.env` files\\n\" +\n \"- Never expose internal error details in API responses\";\n\nexport const SKILL_AUTHORING_CONTENT =\n \"When creating Claude Code skills (.claude/skills/*/SKILL.md):\\n\" +\n \"\\n\" +\n \"- Keep SKILL.md under 500 lines — move reference material to supporting files in the same directory\\n\" +\n \"- Front-load description (first 250 chars shown in listings) with TRIGGER when / DO NOT TRIGGER when clauses\\n\" +\n \"- Add allowed-tools in frontmatter to restrict tool access (e.g. Read, Glob, Grep for read-only skills)\\n\" +\n \"- Add argument-hint in frontmatter showing the expected input format (use $ARGUMENTS or $0, $1 for dynamic input)\\n\" +\n \"- Set disable-model-invocation: true for skills with side effects (deploy, send messages)\\n\" +\n \"- Structure as phases: Research, Plan, Execute, Verify with \\\"Done when:\\\" success criteria per phase\\n\" +\n \"- Handle edge cases and preconditions before execution\";\n\n/**\n * Sprint review checklist: delegate to native /code-review + /security-review,\n * anchored to the sprint's base commit, with the manual pass as fallback.\n * Verification commands are interpolated from stack detection when known.\n */\nexport function sprintReviewsContent(testCommand: string | null, lintCommand: string | null, superpowers = false): string {\n const known = [testCommand, lintCommand].filter((c): c is string => !!c).map((c) => `\\`${c}\\``).join(\" and \");\n const verifyLine = known\n ? `- Run ${known} — must pass before the sprint-ending commit`\n : \"- Run the project's test and typecheck commands — they must pass before the sprint-ending commit\";\n return (\n \"When all tasks in the current sprint are complete, review before the closing commit:\\n\" +\n \"- Find the sprint base: \\`git log --grep 'chore(sprint-' -n 1 --format=%H\\`\\n\" +\n \"- Run /code-review on the diff from that base; fix all Critical and Important findings before committing\\n\" +\n \"- Run /security-review if the sprint touched auth, input handling, or dependencies\\n\" +\n verifyLine + \"\\n\" +\n \"- If /code-review is unavailable, do a manual pass: dead code, debug logs, TODO hacks, convention violations, hardcoded values\\n\" +\n (superpowers\n ? \"- superpowers detected: invoke superpowers:requesting-code-review for the independent pass (severity-gated)\\n\"\n : \"- For an independent second pass, dispatch the code-reviewer agent (.claude/agents/code-reviewer.md) with the base/head SHAs\\n\") +\n \"- Skip only if the sprint was trivial (docs or config-only changes)\"\n );\n}\n\nexport const TESTING_DISCIPLINE_CONTENT =\n \"Hard-TDD surfaces — write the failing test BEFORE any implementation for:\\n\" +\n \"- A new module, command, or public API\\n\" +\n \"- Any bug fix (regression test from the minimal repro first)\\n\" +\n \"- Any algorithm or scoring change\\n\" +\n \"Flexible (tests land in the same commit, order free): docs, config, version bumps, log messages.\\n\" +\n \"If unsure which bucket a change falls into, default to test-first.\";\n","import { join, basename } from \"node:path\";\nimport { fileExists, readFileOrNull, readJsonOrNull } from \"./fs-utils.js\";\nimport type { DetectedProject } from \"../types/index.js\";\n\n/**\n * Detect project characteristics by scanning manifest files and directory structure.\n * Works with any stack — no hardcoded list of supported frameworks.\n */\nexport async function detectProject(root: string): Promise<DetectedProject> {\n const name = basename(root);\n\n const [pkgJson, goMod, pyProject, gemfile, cargo, pubspec, composerJson, pomXml, buildGradleGroovy, buildGradleKts, packageSwift, mixExs, csproj, lockfiles] = await Promise.all([\n readJsonOrNull<PackageJson>(join(root, \"package.json\")),\n fileExists(join(root, \"go.mod\")),\n readFileOrNull(join(root, \"pyproject.toml\")),\n fileExists(join(root, \"Gemfile\")),\n fileExists(join(root, \"Cargo.toml\")),\n fileExists(join(root, \"pubspec.yaml\")),\n readJsonOrNull<ComposerJson>(join(root, \"composer.json\")),\n fileExists(join(root, \"pom.xml\")),\n fileExists(join(root, \"build.gradle\")),\n fileExists(join(root, \"build.gradle.kts\")),\n fileExists(join(root, \"Package.swift\")),\n fileExists(join(root, \"mix.exs\")),\n globExists(root, \"*.csproj\"),\n detectLockfiles(root),\n ]);\n\n const buildGradle = buildGradleGroovy || buildGradleKts;\n\n const manifests: ManifestState = {\n pkgJson, goMod, pyProject, gemfile, cargo, pubspec,\n composerJson, pomXml, buildGradle, packageSwift, mixExs, csproj,\n };\n\n const language = detectLanguage(manifests);\n const framework = detectFramework(manifests);\n const packageManager = detectPackageManager(manifests, lockfiles);\n const scripts = detectScripts({ pkgJson, pyProject, goMod, gemfile, composerJson, language, packageManager });\n\n return {\n name,\n language,\n framework,\n packageManager,\n hasTests: scripts.testCommand !== null,\n hasLinter: scripts.lintCommand !== null,\n hasFormatter: scripts.formatCommand !== null,\n ...scripts,\n };\n}\n\n// ─── Language Detection ───\n\ninterface ManifestState {\n pkgJson: PackageJson | null;\n goMod: boolean;\n pyProject: string | null;\n gemfile: boolean;\n cargo: boolean;\n pubspec: boolean;\n composerJson: ComposerJson | null;\n pomXml: boolean;\n buildGradle: boolean;\n packageSwift: boolean;\n mixExs: boolean;\n csproj: boolean;\n}\n\nfunction detectLanguage(m: ManifestState): string | null {\n if (m.pkgJson?.devDependencies?.typescript || m.pkgJson?.dependencies?.typescript) return \"TypeScript\";\n if (m.pkgJson) return \"JavaScript\";\n if (m.goMod) return \"Go\";\n if (m.pyProject) return \"Python\";\n if (m.gemfile) return \"Ruby\";\n if (m.cargo) return \"Rust\";\n if (m.pubspec) return \"Dart\";\n if (m.composerJson) return \"PHP\";\n if (m.buildGradle) return \"Kotlin\";\n if (m.pomXml) return \"Java\";\n if (m.packageSwift) return \"Swift\";\n if (m.mixExs) return \"Elixir\";\n if (m.csproj) return \"C#\";\n return null;\n}\n\n// ─── Framework Detection ───\n\nfunction detectFramework(m: ManifestState): string | null {\n const deps = { ...m.pkgJson?.dependencies, ...m.pkgJson?.devDependencies };\n\n // JS/TS frameworks\n if (deps.next) return \"Next.js\";\n if (deps.nuxt) return \"Nuxt\";\n if (deps.svelte || deps[\"@sveltejs/kit\"]) return \"SvelteKit\";\n if (deps.astro) return \"Astro\";\n if (deps[\"@angular/core\"]) return \"Angular\";\n if (deps.remix || deps[\"@remix-run/react\"]) return \"Remix\";\n if (deps.vue) return \"Vue\";\n if (deps.react && !deps.next) return \"React\";\n if (deps.express) return \"Express\";\n if (deps.fastify) return \"Fastify\";\n if (deps.hono) return \"Hono\";\n if (deps.nestjs || deps[\"@nestjs/core\"]) return \"NestJS\";\n\n // Python frameworks\n if (m.pyProject) {\n if (m.pyProject.includes(\"fastapi\")) return \"FastAPI\";\n if (m.pyProject.includes(\"django\")) return \"Django\";\n if (m.pyProject.includes(\"flask\")) return \"Flask\";\n }\n\n // PHP frameworks\n if (m.composerJson) {\n const phpDeps = { ...m.composerJson.require, ...m.composerJson[\"require-dev\"] };\n if (phpDeps[\"laravel/framework\"]) return \"Laravel\";\n if (phpDeps[\"symfony/framework-bundle\"]) return \"Symfony\";\n }\n\n // Ruby\n if (m.gemfile) return \"Rails\";\n\n // JVM\n if (m.buildGradle) return \"Gradle\"; // Could be Spring Boot, Android, etc.\n if (m.pomXml) return \"Maven\";\n\n return null;\n}\n\n// ─── Package Manager Detection ───\n\ninterface DetectedLockfiles {\n pnpmLock: boolean;\n yarnLock: boolean;\n bunLock: boolean;\n npmLock: boolean;\n}\n\nasync function detectLockfiles(root: string): Promise<DetectedLockfiles> {\n const [pnpmLock, yarnLock, bunLock, npmLock] = await Promise.all([\n fileExists(join(root, \"pnpm-lock.yaml\")),\n fileExists(join(root, \"yarn.lock\")),\n fileExists(join(root, \"bun.lockb\")),\n fileExists(join(root, \"package-lock.json\")),\n ]);\n return { pnpmLock, yarnLock, bunLock, npmLock };\n}\n\nfunction detectPackageManager(\n m: Pick<ManifestState, \"pkgJson\" | \"goMod\" | \"pyProject\" | \"gemfile\" | \"cargo\" | \"composerJson\">,\n lockfiles: DetectedLockfiles,\n): string | null {\n if (m.pkgJson) {\n // Check packageManager field first (most explicit)\n const pm = m.pkgJson.packageManager;\n if (pm?.startsWith(\"pnpm\")) return \"pnpm\";\n if (pm?.startsWith(\"yarn\")) return \"yarn\";\n if (pm?.startsWith(\"bun\")) return \"bun\";\n if (pm?.startsWith(\"npm\")) return \"npm\";\n\n // Fall back to lockfile detection\n if (lockfiles.pnpmLock) return \"pnpm\";\n if (lockfiles.yarnLock) return \"yarn\";\n if (lockfiles.bunLock) return \"bun\";\n if (lockfiles.npmLock) return \"npm\";\n\n return \"npm\";\n }\n if (m.goMod) return \"go modules\";\n if (m.pyProject) {\n if (m.pyProject.includes(\"[tool.uv]\")) return \"uv\";\n if (m.pyProject.includes(\"[tool.poetry]\")) return \"poetry\";\n return \"pip\";\n }\n if (m.gemfile) return \"bundler\";\n if (m.cargo) return \"cargo\";\n if (m.composerJson) return \"composer\";\n return null;\n}\n\n// ─── Script Detection ───\n\ninterface DetectedScripts {\n formatCommand: string | null;\n lintCommand: string | null;\n testCommand: string | null;\n devCommand: string | null;\n buildCommand: string | null;\n}\n\n// Language → default scripts config\nconst LANGUAGE_SCRIPTS: Record<string, DetectedScripts> = {\n Go: { devCommand: \"go run .\", buildCommand: \"go build .\", testCommand: \"go test ./...\", lintCommand: \"golangci-lint run\", formatCommand: \"gofmt -w .\" },\n Ruby: { devCommand: \"bin/dev\", buildCommand: null, testCommand: \"bin/rails test\", lintCommand: \"bin/rubocop\", formatCommand: null },\n PHP: { devCommand: \"php artisan serve\", buildCommand: null, testCommand: \"php artisan test\", lintCommand: \"vendor/bin/phpstan analyse\", formatCommand: \"vendor/bin/pint\" },\n Rust: { devCommand: \"cargo run\", buildCommand: \"cargo build\", testCommand: \"cargo test\", lintCommand: \"cargo clippy\", formatCommand: \"cargo fmt\" },\n Java: { devCommand: null, buildCommand: \"mvn package\", testCommand: \"mvn test\", lintCommand: null, formatCommand: null },\n Kotlin: { devCommand: null, buildCommand: \"mvn package\", testCommand: \"mvn test\", lintCommand: null, formatCommand: null },\n Swift: { devCommand: null, buildCommand: \"swift build\", testCommand: \"swift test\", lintCommand: \"swiftlint\", formatCommand: \"swift-format format -r .\" },\n Elixir: { devCommand: \"mix phx.server\", buildCommand: \"mix compile\", testCommand: \"mix test\", lintCommand: \"mix credo\", formatCommand: \"mix format\" },\n \"C#\": { devCommand: \"dotnet run\", buildCommand: \"dotnet build\", testCommand: \"dotnet test\", lintCommand: null, formatCommand: \"dotnet format\" },\n};\n\nfunction detectScripts(m: {\n pkgJson: PackageJson | null;\n pyProject: string | null;\n goMod: boolean;\n gemfile: boolean;\n composerJson: ComposerJson | null;\n language: string | null;\n packageManager: string | null;\n}): DetectedScripts {\n // JS/TS: read from package.json scripts\n if (m.pkgJson) {\n const scripts = m.pkgJson.scripts ?? {};\n const run = pmRun(m.packageManager);\n return {\n devCommand: scripts.dev ? `${run} dev` : null,\n buildCommand: scripts.build ? `${run} build` : null,\n testCommand: scripts.test ? `${run} test` : null,\n lintCommand: scripts.lint ? `${run} lint` : null,\n formatCommand: scripts.format ? `${run} format` : null,\n };\n }\n\n // Python: runner depends on uv vs pip\n if (m.language === \"Python\") {\n const r = m.pyProject?.includes(\"[tool.uv]\") ? \"uv run\" : \"python -m\";\n return { devCommand: null, buildCommand: null, testCommand: `${r} pytest`, lintCommand: `${r} ruff check .`, formatCommand: `${r} ruff format .` };\n }\n\n // Everything else: lookup table\n if (m.language && LANGUAGE_SCRIPTS[m.language]) {\n return LANGUAGE_SCRIPTS[m.language];\n }\n\n return { devCommand: null, buildCommand: null, testCommand: null, lintCommand: null, formatCommand: null };\n}\n\nfunction pmRun(packageManager: string | null): string {\n if (packageManager === \"pnpm\") return \"pnpm\";\n if (packageManager === \"yarn\") return \"yarn\";\n if (packageManager === \"bun\") return \"bun\";\n return \"npm run\";\n}\n\n// ─── Utilities ───\n\ninterface PackageJson {\n name?: string;\n packageManager?: string;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\ninterface ComposerJson {\n require?: Record<string, string>;\n \"require-dev\"?: Record<string, string>;\n}\n\nasync function globExists(dir: string, pattern: string): Promise<boolean> {\n const { readdir } = await import(\"node:fs/promises\");\n try {\n const entries = await readdir(dir);\n return entries.some((e) => e.endsWith(pattern.replace(\"*\", \"\")));\n } catch {\n return false;\n }\n}\n","import type { DetectedProject } from \"../../../types/index.js\";\n\n/**\n * Generate .claudeignore based on detected project type.\n * Prevents Claude from reading noise files that waste context.\n */\nexport function generateClaudeignore(detected: DetectedProject): string {\n const sections: string[] = [\"# Generated by claude-launchpad\"];\n\n // Universal ignores (every project)\n sections.push(`\n# Build output\ndist/\nbuild/\nout/\n\n# IDE & OS\n.vscode/\n.idea/\n*.swp\n*.swo\n.DS_Store\nThumbs.db\n\n# Test & coverage\ncoverage/\n\n# Environment (should never be read)\n.env\n.env.*\n!.env.example`);\n\n // Language-specific ignores\n const lang = detected.language;\n\n if (lang === \"TypeScript\" || lang === \"JavaScript\") {\n sections.push(`\n# Node\nnode_modules/\n.pnp/\n.yarn/\n.next/\n.nuxt/\n.output/\n.svelte-kit/\n.vercel/\n.turbo/\npnpm-lock.yaml\npackage-lock.json\nyarn.lock\nbun.lockb\n.nyc_output/\n__snapshots__/`);\n }\n\n if (lang === \"Python\") {\n sections.push(`\n# Python\n__pycache__/\n*.pyc\n*.pyo\n.venv/\nvenv/\n.mypy_cache/\n.ruff_cache/\n.pytest_cache/\n*.egg-info/`);\n }\n\n if (lang === \"Go\") {\n sections.push(`\n# Go\nbin/\nvendor/`);\n }\n\n if (lang === \"Rust\") {\n sections.push(`\n# Rust\ntarget/\nCargo.lock`);\n }\n\n if (lang === \"Ruby\") {\n sections.push(`\n# Ruby\nvendor/bundle/\n.bundle/\ntmp/\nlog/`);\n }\n\n if (lang === \"Java\" || lang === \"Kotlin\") {\n sections.push(`\n# JVM\ntarget/\nbuild/\n.gradle/\n*.class\n*.jar`);\n }\n\n if (lang === \"Dart\") {\n sections.push(`\n# Dart/Flutter\n.dart_tool/\n.packages\nbuild/`);\n }\n\n if (lang === \"PHP\") {\n sections.push(`\n# PHP\nvendor/\ncomposer.lock`);\n }\n\n if (lang === \"C#\") {\n sections.push(`\n# .NET\nbin/\nobj/\n*.dll`);\n }\n\n if (lang === \"Elixir\") {\n sections.push(`\n# Elixir\n_build/\ndeps/\n.elixir_ls/`);\n }\n\n if (lang === \"Swift\") {\n sections.push(`\n# Swift\n.build/\nDerivedData/\n*.xcuserdata`);\n }\n\n return sections.join(\"\\n\") + \"\\n\";\n}\n","import { SKILL_AUTHORING_CONTENT } from \"../../../lib/sections.js\";\n\n/**\n * Skill schema version. Bump this when the skill content changes.\n * Doctor compares this against installed skills to detect stale versions.\n */\nexport const ENHANCE_SKILL_VERSION = 10;\n\n/**\n * Generates the /lp-enhance skill markdown content.\n * This skill runs inside the user's active Claude Code session\n * to analyze the codebase and improve CLAUDE.md.\n */\nexport function generateEnhanceSkill(): string {\n return [\n '---',\n 'name: lp-enhance',\n 'description: |',\n ' AI-improve your CLAUDE.md based on codebase analysis. Fills in architecture, conventions, guardrails, and suggests hooks and MCP servers.',\n ' TRIGGER when: user runs /lp-enhance, asks to \"improve CLAUDE.md\", \"fill in architecture\", or after major refactors.',\n ' DO NOT TRIGGER when: user is editing CLAUDE.md manually, doing normal coding, or running doctor/eval.',\n 'allowed-tools: Read, Glob, Grep, Edit, Write, Bash(claude-launchpad doctor:*)',\n 'argument-hint: (no arguments needed)',\n '---',\n '',\n `<!-- lp-enhance-version: ${ENHANCE_SKILL_VERSION} -->`,\n '',\n '# lp-enhance - AI-powered CLAUDE.md improver',\n '',\n 'Read CLAUDE.md and the project\\'s codebase, then update CLAUDE.md to fill in missing or incomplete sections.',\n '',\n '## Phase 1: Research',\n '',\n '1. Read CLAUDE.md (if it exists)',\n '2. Read .claude/CLAUDE.md (local config, if it exists)',\n '3. Read .claude/settings.json (hooks, permissions, MCP)',\n '4. Read .claude/settings.local.json (local settings, if it exists)',\n '5. Read .claude/rules/*.md (existing rules)',\n '6. Read .claudeignore (if it exists)',\n '7. Scan src/ directory structure (top-level dirs, key files)',\n '8. Read package.json / go.mod / pyproject.toml for stack detection',\n '9. Check for monorepo indicators (workspaces, nx.json, lerna.json)',\n '10. Check scenarios/ directory for existing eval scenarios',\n '',\n '**Done when:** you have a mental model of the stack, architecture, and existing config.',\n '',\n '## Phase 2: Plan',\n '',\n 'Count current CLAUDE.md actionable lines. Budget is 200 lines max. Plan which sections to add or improve:',\n '',\n '1. **## Stack** - detect language, framework, package manager',\n '2. **## Architecture** - 3-5 bullets describing codebase shape',\n '3. **## Conventions** - max 8 key patterns. Overflow to .claude/rules/conventions.md',\n '4. **## Off-Limits** - max 8 guardrails specific to this project',\n '5. **## Memory (agentic-memory)** - ONLY if agentic-memory is configured in settings.json. Max 6 bullets. Use this exact heading so `memory install` stays idempotent.',\n '6. **## Key Decisions** - only decisions that affect how Claude works in this codebase',\n '',\n '7. **Skill Authoring** - if .claude/rules/conventions.md lacks a Skill Authoring section, plan to add one',\n '',\n 'If any section would exceed 8 bullets, plan a .claude/rules/ file for the overflow.',\n '',\n '**Done when:** you know exactly what to add/change and the line count stays under 200.',\n '',\n '## Phase 3: Execute',\n '',\n 'Edit CLAUDE.md with the planned changes. Then:',\n '',\n '1. Create or update .claude/rules/ files for overflow content',\n '2. Generate path-scoped rules if the project has distinct areas (see below)',\n '3. Review .claudeignore and print suggestions (see below)',\n '4. Generate 2-3 custom eval scenarios in scenarios/custom/ (see below)',\n '5. Verify line count is under 200',\n '',\n '**Rules:**',\n '- Don\\'t remove existing content, only add or improve',\n '- Be specific to THIS project, not generic advice',\n '- Use bullet points, not paragraphs',\n '',\n '## Phase 4: Verify',\n '',\n '1. Run `claude-launchpad doctor` to check the score improved',\n '2. Print suggested hooks (exact JSON) for .claude/settings.json but don\\'t modify it',\n '3. Print suggested MCP servers if external services detected (Postgres, Redis, Stripe, etc.)',\n '4. If eval scenarios were generated, print: \"Run this in your terminal (not inside Claude Code): `claude-launchpad eval --scenarios scenarios/ --runs 1`\"',\n '',\n '**Done when:** doctor score is equal or higher, suggestions printed, eval scenarios created if applicable.',\n '',\n '## Path-scoped rules generation',\n '',\n 'Scan the project structure and generate focused .claude/rules/ files with paths: frontmatter. These load ONLY when Claude works on matching files, saving context tokens.',\n '',\n '**How to detect areas:**',\n '1. List top-level directories under src/ (or equivalent). Each distinct area (api, components, lib, tests) is a candidate.',\n '2. Check for monorepo indicators: workspaces in package.json, pnpm-workspace.yaml, nx.json, lerna.json. Each workspace is a candidate.',\n '3. Check for docs/, tests/, scripts/ as separate scopes.',\n '',\n '**For each detected area, create a rules file with this format:**',\n '',\n '---',\n 'paths: [\"src/api/**\"]',\n '---',\n '# API Rules',\n '- Validate all request input with zod schemas',\n '- Return typed error responses, never throw raw errors',\n '- Keep route handlers under 30 lines',\n '',\n '**Stack-specific patterns to include:**',\n '- Next.js app/: \"Use Server Components by default, add \\'use client\\' only when needed\"',\n '- API routes / src/api/: \"Validate input at boundaries, typed error responses\"',\n '- React components: \"Colocate components near usage, props interface above component\"',\n '- Tests: \"One assertion per test when possible, descriptive test names\"',\n '- Database / prisma/ / drizzle/: \"Never write raw SQL, use the ORM, migrations required\"',\n '- Docs: \"No em dashes, max 3 sentences per paragraph, code examples required\"',\n '',\n '**When NOT to generate:**',\n '- Small projects with < 5 source files (one conventions.md is enough)',\n '- Projects where all code is in one flat directory',\n '- If path-scoped rules already exist, don\\'t overwrite them',\n '',\n '**Monorepo handling:**',\n '- Each package gets its own rules file: .claude/rules/packages-<name>.md',\n '- Suggest claudeMdExcludes in settings.json to skip irrelevant package CLAUDE.md files',\n '',\n '## Skill authoring conventions',\n '',\n 'If .claude/rules/conventions.md exists but has no Skill Authoring section, add this:',\n '',\n '## Skill Authoring',\n '',\n ...SKILL_AUTHORING_CONTENT.split('\\n'),\n '',\n '## Hook review',\n '',\n 'Review .claude/settings.json hooks:',\n '- If you see project-specific patterns that deserve hooks, suggest them',\n '- If the SessionStart matcher misses compact/clear, suggest widening it to startup|resume|compact|clear (PostCompact stdout is never injected into context - context re-injection belongs on SessionStart)',\n '- If no SessionStart hook exists, suggest one that injects TASKS.md',\n '- DO NOT modify settings.json directly. Print exact JSON to add.',\n '',\n '## .claudeignore review',\n '',\n 'Read .claudeignore and check if the patterns make sense for the detected stack:',\n '',\n '**Always flag:**',\n '- Missing node_modules/ (JS/TS projects)',\n '- Missing __pycache__/ or .venv/ (Python projects)',\n '- Missing target/ (Rust/Java projects)',\n '- Missing .env / .env.* patterns',\n '- Missing lock files (pnpm-lock.yaml, package-lock.json, yarn.lock, etc.)',\n '- Missing coverage/ directory',\n '- Large generated files that waste context (*.min.js, *.map, migrations/)',\n '',\n '**Never flag:**',\n '- Patterns the user clearly added intentionally',\n '- Test fixtures or seed data (might be needed for context)',\n '',\n 'If .claudeignore is missing entirely, create one with sensible defaults for the detected stack.',\n 'If it exists but has gaps, print suggested additions. Do NOT modify it directly.',\n '',\n '## Eval scenario generation',\n '',\n 'After improving CLAUDE.md, generate 2-3 custom eval scenarios that test whether Claude follows the project\\'s specific rules. Write them as YAML files in scenarios/ at the project root.',\n '',\n '**Scenario YAML format:**',\n '```yaml',\n 'name: custom/scenario-name',\n 'description: What this scenario tests',\n 'setup:',\n ' files:',\n ' - path: src/example.ts',\n ' content: |',\n ' // Starter file that tempts Claude to break a rule',\n ' instructions: |',\n ' The specific rule from CLAUDE.md being tested.',\n 'prompt: \"A task that would tempt Claude to break the rule\"',\n 'checks:',\n ' - type: grep',\n ' pattern: \"expected_pattern\"',\n ' target: src/example.ts',\n ' expect: present',\n ' points: 5',\n ' label: What this check verifies',\n ' - type: file-exists',\n ' target: path/to/expected/file',\n ' expect: present',\n ' points: 5',\n ' label: What this check verifies',\n 'passingScore: 7',\n 'runs: 3',\n '```',\n '',\n '**How to choose scenarios:**',\n '1. Pick the 2-3 most important rules from ## Off-Limits and ## Conventions',\n '2. Design a task that naturally tempts Claude to break each rule',\n '3. Write checks that verify compliance (grep for patterns, file-exists for structure)',\n '',\n '**Check types available:** `grep` (pattern in file), `file-exists` (present/absent), `max-lines` (file length)',\n '',\n '**Examples of good custom scenarios:**',\n '- Off-limits says \"never use any\" → task asks to build types, check for no `any` keyword',\n '- Convention says \"max 400 lines per file\" → task asks to generate a large module, check line count',\n '- Off-limits says \"no raw SQL\" → task asks to add a query, check for ORM usage',\n '',\n '**Skip if:** scenarios/ already has 3+ YAML files, or CLAUDE.md has no project-specific rules worth testing.',\n '',\n '## Other advanced configuration',\n '',\n '- If you detect a monorepo, suggest claudeMdExcludes in settings.json',\n ].join('\\n');\n}\n","import type { InitOptions } from \"../../../types/index.js\";\n\nexport function generateBacklogMd(options: InitOptions): string {\n const today = new Date().toISOString().slice(0, 10);\n return `# ${options.name} — Backlog\n\n> **Single source of truth for future work.** Every work package (WP) that's been proposed but not yet started lives here.\n>\n> Rules (see \\`.claude/rules/workflow.md\\` for the full lifecycle):\n> - Every WP uses the template below — no freeform entries.\n> - WPs are **moved** to \\`TASKS.md\\` when pulled into a sprint, not copied. A WP lives in exactly one file at a time.\n> - Priority ordering: **P0 > P1 > P2 > P3**. P0 items sit at the top.\n> - A WP ID is minted when the WP is first added here and never reused.\n\n---\n\n## Priority definitions\n\n| Priority | Meaning |\n|---|---|\n| **P0** | Blocks launch or an active sprint. Next sprint or sooner. |\n| **P1** | Important for MVP. Pulled within 2–3 sprints. |\n| **P2** | Post-MVP or nice-to-have. Review monthly. |\n| **P3** | Parked idea. Review quarterly; delete if still untouched. |\n\n---\n\n## Work package template (copy this exactly)\n\n\\`\\`\\`markdown\n### WP-NNN — <short imperative title>\n\n- **Priority:** P0 | P1 | P2 | P3\n- **Proposed:** YYYY-MM-DD\n- **Stories / Docs:** links to specs, issues, or \"none yet\"\n- **Depends on:** WP-MMM (empty if none)\n- **Estimate:** XS (<1h) | S (half-day) | M (1–2 days) | L (full sprint) | XL (>1 sprint; must decompose)\n- **Trigger to pull:** What has to be true before this moves into a sprint.\n- **Definition of done:** Exactly what \"done\" looks like.\n\nOne-paragraph description. Context, rationale, rough approach if known. Keep it tight.\n\\`\\`\\`\n\n**Hard rules for entries:**\n- Title is an imperative (\"Add referral banner\", \"Wire up StoreKit upgrade flow\") — not a noun.\n- \\`Trigger to pull\\` and \\`Definition of done\\` are mandatory. A WP without either is incomplete.\n- \\`XL\\` estimates must be broken into multiple WPs before pulling into a sprint.\n- WP IDs are minted on first entry and never reused. Check the Changelog below for the highest ID before adding a new one.\n\n---\n\n## P0 — Next sprint\n\n<!-- Empty. WPs appear here when promoted from P1, or when a new blocker surfaces. -->\n\n---\n\n## P1 — Soon (within 2–3 sprints)\n\n<!-- Empty. Add WPs here as sprints approach. -->\n\n---\n\n## P2 — Post-MVP / nice-to-have\n\n<!-- Empty. Review monthly. -->\n\n---\n\n## P3 — Parked\n\n<!-- Empty. Move P2 items here if they survive 2 quarterly reviews without being pulled. -->\n\n---\n\n## Changelog\n\nCapture WP promotions, demotions, and deletions so you can audit backlog drift.\n\n- ${today}: Backlog established.\n`;\n}\n","import { select } from \"@inquirer/prompts\";\nimport { readSettingsJson, readSettingsLocalJson, writeSettingsLocalJson } from \"./settings.js\";\nimport type { MemoryPlacement } from \"../types/index.js\";\n\nfunction hasMemoryPermissions(settings: Record<string, unknown>): boolean {\n const permissions = settings.permissions as Record<string, unknown> | undefined;\n const allow = (permissions?.allow as string[] | undefined) ?? [];\n return allow.some((p) => p.includes(\"agentic-memory\"));\n}\n\nexport async function getMemoryPlacement(root: string, skipPrompt = false): Promise<MemoryPlacement> {\n const local = (await readSettingsLocalJson(root)) ?? {};\n const persisted = local.memoryPlacement;\n if (persisted === \"shared\" || persisted === \"local\") {\n return persisted;\n }\n\n // Backfill: infer from where agentic-memory permissions already live\n if (hasMemoryPermissions(local)) {\n await writeSettingsLocalJson(root, { ...local, memoryPlacement: \"local\" });\n return \"local\";\n }\n const shared = (await readSettingsJson(root)) ?? {};\n if (hasMemoryPermissions(shared)) {\n await writeSettingsLocalJson(root, { ...local, memoryPlacement: \"shared\" });\n return \"shared\";\n }\n\n if (skipPrompt) return \"shared\";\n\n const choice = await select<MemoryPlacement>({\n message: \"Where should memory config go?\",\n choices: [\n { value: \"shared\", name: \"Shared (team sees it) — CLAUDE.md + settings.json\" },\n { value: \"local\", name: \"Local (only you) — .claude/CLAUDE.md + settings.local.json\" },\n ],\n });\n\n await writeSettingsLocalJson(root, { ...local, memoryPlacement: choice });\n return choice;\n}\n","/**\n * LP-STUB markers wrap AI-recommended boilerplate injected by `doctor --fix`.\n * The intent analyzer treats a marked section as \"not satisfied\" so the user\n * sees the flag until they replace the stub with real content (or delete the markers).\n */\n\nexport const LP_STUB_OPEN = \"<!-- LP-STUB: ai-recommended -->\";\nexport const LP_STUB_CLOSE = \"<!-- /LP-STUB -->\";\n\nexport function wrapStub(content: string): string {\n return `${LP_STUB_OPEN}\\n${content}\\n${LP_STUB_CLOSE}`;\n}\n\nexport function hasStubMarker(text: string): boolean {\n return text.includes(LP_STUB_OPEN);\n}\n","import { writeFile, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { log } from \"../../lib/output.js\";\nimport { addHookToSettings } from \"../../lib/hook-builder.js\";\nimport { readSettingsJson, writeSettingsJson } from \"../../lib/settings.js\";\nimport {\n writeSprintHygieneScripts, writeWorkflowCheckScript,\n WORKFLOW_CHECK_WRAPPER, SPRINT_OPEN_WRAPPER, SPRINT_SIZE_WRAPPER,\n SESSION_START_MATCHER, SPRINT_COMPLETE_NUDGE,\n} from \"../../lib/hook-scripts.js\";\n\nconst WORKTREE_INCLUDE_TEMPLATE = `# Files copied into git worktrees that Claude Code creates for subagents.\n# Listed files must be gitignored — that's the point: keep secrets out of\n# commits while letting worktree subagents inherit local env so dev servers,\n# tests, and integration runs work the same as the main tree.\n# Anything needed by \\`pnpm dev\\`, \\`pnpm test\\`, etc. that's NOT committed\n# should land here.\n\n.env.local\n.env\n`;\n\nexport async function createWorktreeInclude(root: string): Promise<boolean> {\n await writeFile(join(root, \".worktreeinclude\"), WORKTREE_INCLUDE_TEMPLATE);\n log.success(\"Generated .worktreeinclude (worktree subagents inherit .env.local / .env)\");\n return true;\n}\n\nexport async function addSprintSizeHook(root: string): Promise<boolean> {\n await writeSprintHygieneScripts(root);\n return addHookToSettings(root, \"SessionStart\", \"sprint-size-check.sh\", {\n matcher: SESSION_START_MATCHER,\n hooks: [{ type: \"command\", command: SPRINT_SIZE_WRAPPER }],\n }, \"Added sprint-size-check hook (warns on microsprint/oversized sprints)\");\n}\n\nexport async function addSprintOpenHook(root: string): Promise<boolean> {\n await writeSprintHygieneScripts(root);\n // PostToolUse, not PreToolUse: only PostToolUse can inject non-blocking context.\n return addHookToSettings(root, \"PostToolUse\", \"sprint-open-check.sh\", {\n matcher: \"Bash\",\n hooks: [{ type: \"command\", command: SPRINT_OPEN_WRAPPER }],\n }, \"Added sprint-open-check hook (warns on WP pulls without BACKLOG cleanup)\");\n}\n\nexport async function addSprintCompleteNudge(root: string): Promise<boolean> {\n return addHookToSettings(root, \"PostToolUse\", \"Sprint complete\", {\n matcher: \"Edit|Write\",\n hooks: [{ type: \"command\", command: SPRINT_COMPLETE_NUDGE }],\n }, \"Added sprint-complete nudge hook\");\n}\n\nexport async function addWorkflowCheckHook(root: string): Promise<boolean> {\n await writeWorkflowCheckScript(root);\n return addHookToSettings(root, \"PostToolUse\", \"workflow-check.sh\", {\n matcher: \"Edit|Write\",\n hooks: [{ type: \"command\", command: WORKFLOW_CHECK_WRAPPER }],\n }, \"Added workflow-check hook (BACKLOG/TASKS staleness warnings)\");\n}\n\n/** Pre-v1.12: sprint-open-check ran on PreToolUse, where context injection is impossible. */\nexport async function migrateSprintOpenHookEvent(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n\n const preToolUse = (hooks.PreToolUse ?? []) as Record<string, unknown>[];\n let removed = false;\n const cleaned = preToolUse\n .map((group) => {\n const nested = (group.hooks ?? []) as Record<string, unknown>[];\n const filtered = nested.filter((h) => !String(h.command ?? \"\").includes(\"sprint-open-check.sh\"));\n if (filtered.length !== nested.length) removed = true;\n return { ...group, hooks: filtered };\n })\n .filter((group) => (group.hooks as unknown[]).length > 0);\n if (!removed) return false;\n\n await writeSettingsJson(root, { ...settings, hooks: { ...hooks, PreToolUse: cleaned as unknown[] } });\n await writeSprintHygieneScripts(root);\n await addSprintOpenHook(root);\n log.success(\"Moved sprint-open-check to PostToolUse (context injection is impossible on PreToolUse)\");\n return true;\n}\n\n/** Pre-v1.12: the sprint-complete nudge echoed to stdout, which the model never sees. */\nexport async function upgradeStaleNudge(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n\n let changed = false;\n const upgraded = Object.fromEntries(Object.entries(hooks).map(([event, groups]) => [\n event,\n (groups as Record<string, unknown>[]).map((group) => ({\n ...group,\n hooks: ((group.hooks ?? []) as Record<string, unknown>[]).map((h) => {\n const cmd = String(h.command ?? \"\");\n if (cmd.includes(\"Sprint complete\") && !cmd.includes(\"additionalContext\")) {\n changed = true;\n return { ...h, command: SPRINT_COMPLETE_NUDGE };\n }\n return h;\n }),\n })),\n ]));\n if (!changed) return false;\n\n await writeSettingsJson(root, { ...settings, hooks: upgraded });\n log.success(\"Upgraded sprint-complete nudge to additionalContext JSON (was invisible bare stdout)\");\n return true;\n}\n\n/** Rewrite pre-v1.12 hygiene scripts whose warnings never reached the model. */\nexport async function refreshHygieneScripts(root: string): Promise<boolean> {\n const scripts = [\".claude/hooks/workflow-check.sh\", \".claude/hooks/sprint-open-check.sh\"];\n let stale = false;\n for (const rel of scripts) {\n const content = await readFile(join(root, rel), \"utf-8\").catch(() => null);\n if (content !== null && !content.includes(\"hookSpecificOutput\")) stale = true;\n }\n if (!stale) return false;\n\n await writeSprintHygieneScripts(root);\n await writeWorkflowCheckScript(root);\n log.success(\"Refreshed hygiene scripts (warnings now emitted as additionalContext JSON)\");\n return true;\n}\n","import { readSettingsJson, writeSettingsJson } from \"./settings.js\";\nimport { log } from \"./output.js\";\n\nexport interface HookCommand {\n readonly type: \"command\";\n readonly command: string;\n readonly timeout?: number;\n}\n\nexport interface HookEntry {\n readonly matcher?: string;\n readonly hooks: ReadonlyArray<HookCommand>;\n}\n\nexport interface AddHookOptions {\n readonly event: string;\n readonly dedupKeyword: string;\n readonly entry: HookEntry;\n readonly prepend?: boolean;\n}\n\nexport interface AddHookResult {\n readonly hooks: Record<string, unknown[]>;\n readonly added: boolean;\n}\n\nexport function addOrUpdateHook(\n existingHooks: Record<string, unknown[]> | undefined,\n options: AddHookOptions,\n): AddHookResult {\n const hookList = (existingHooks?.[options.event] ?? []) as Record<string, unknown>[];\n\n const alreadyHas = hookList.some((group) => {\n const nested = group.hooks as Record<string, unknown>[] | undefined;\n return nested?.some((h) => String(h.command ?? \"\").includes(options.dedupKeyword));\n });\n\n if (alreadyHas) {\n return { hooks: (existingHooks ?? {}) as Record<string, unknown[]>, added: false };\n }\n\n // Two top-level entries with the same matcher are undefined behavior\n // (see .claude/rules/hooks.md) — merge into the existing entry instead.\n const matcher = options.entry.matcher ?? \"\";\n const sameMatcherIdx = hookList.findIndex((g) => String(g.matcher ?? \"\") === matcher);\n if (sameMatcherIdx >= 0) {\n const group = hookList[sameMatcherIdx];\n const existing = (group.hooks ?? []) as Record<string, unknown>[];\n const incoming = options.entry.hooks as unknown as Record<string, unknown>[];\n const merged = {\n ...group,\n hooks: options.prepend ? [...incoming, ...existing] : [...existing, ...incoming],\n };\n const updated = hookList.map((g, i) => (i === sameMatcherIdx ? merged : g));\n return {\n hooks: { ...(existingHooks ?? {}), [options.event]: updated },\n added: true,\n };\n }\n\n const newEntry = options.entry as unknown as Record<string, unknown>;\n const updated = options.prepend ? [newEntry, ...hookList] : [...hookList, newEntry];\n return {\n hooks: { ...(existingHooks ?? {}), [options.event]: updated },\n added: true,\n };\n}\n\nexport async function addHookToSettings(\n root: string,\n event: string,\n dedupKeyword: string,\n entry: HookEntry,\n successMsg: string,\n): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const existingHooks = settings.hooks as Record<string, unknown[]> | undefined;\n\n const result = addOrUpdateHook(existingHooks, { event, dedupKeyword, entry });\n if (!result.added) return false;\n\n await writeSettingsJson(root, { ...settings, hooks: result.hooks });\n log.success(successMsg);\n return true;\n}\n","import { writeFile, mkdir, chmod } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { jqField } from \"./hook-input.js\";\n\nexport const SPRINT_SIZE_CHECK = `#!/usr/bin/env bash\n# Warns when the current sprint is too small (<3) or too large (>7 soft; 15 is\n# the hard split trigger enforced by workflow-check). Sweet spot is 3-6 work\n# packages. Runs on SessionStart, whose stdout is injected into context.\n# Non-blocking (always exits 0).\n\nset -u\ntasks=\"\\${1:-TASKS.md}\"\n[ -f \"$tasks\" ] || exit 0\n\nsection=$(sed -n '/^## Current/,/^## /p' \"$tasks\" 2>/dev/null)\n[ -z \"$section\" ] && exit 0\n\n# Anchored so placeholder comments containing \"- [ ]\" don't count as WPs.\nunchecked=$(echo \"$section\" | grep -cE '^[[:space:]]*- \\\\[ \\\\]' || true)\nchecked=$(echo \"$section\" | grep -cE '^[[:space:]]*- \\\\[[xX]\\\\]' || true)\ntotal=$((unchecked + checked))\n\nif [ \"$total\" -eq 0 ]; then\n echo \"NOTE: Current sprint has no work packages yet. Pull 3-6 from BACKLOG.md to start.\"\n exit 0\nfi\n\nif [ \"$unchecked\" -eq 0 ]; then exit 0; fi\n\nif [ \"$unchecked\" -lt 3 ]; then\n echo \"NOTE: Current sprint has $unchecked open work package(s) — that's a microsprint. Pull from BACKLOG.md (aim 3-6).\"\n exit 0\nfi\n\nif [ \"$unchecked\" -gt 7 ]; then\n echo \"NOTE: Current sprint has $unchecked open work packages — oversized (soft target 3-6; above 15, workflow-check requires a split).\"\n exit 0\nfi\n\nexit 0\n`;\n\nexport const SPRINT_OPEN_CHECK = `#!/usr/bin/env bash\n# After a git commit, warns when the commit adds WP checkboxes to\n# '## Current Sprint' without deleting anything from BACKLOG.md — i.e. the\n# \"pull = move, not copy\" rule was skipped. Runs on PostToolUse (Bash):\n# PreToolUse has no non-blocking way to reach the model, so instead of\n# blocking the commit we suggest an amend. Warning is emitted as\n# additionalContext JSON — bare stdout on PostToolUse never reaches the model.\n# Non-blocking (always exits 0).\n\nset -u\ncommand -v jq >/dev/null 2>&1 || exit 0\ncmd=$(jq -r '.tool_input.command // empty' 2>/dev/null)\n\n# Only act on \\\\\\`git commit\\\\\\`, word-boundary match.\necho \"$cmd\" | grep -qE '(^|[^a-zA-Z0-9_-])git[[:space:]]+commit([[:space:]]|$)' || exit 0\n\ngit rev-parse --verify HEAD >/dev/null 2>&1 || exit 0\n\n# The commit must touch TASKS.md and add unchecked WP lines to it.\ngit show --name-only --format= HEAD 2>/dev/null | grep -qx 'TASKS.md' || exit 0\npulled=$(git show --format= HEAD -- TASKS.md 2>/dev/null | grep -cE '^\\\\+[[:space:]]*- \\\\[ \\\\] WP-' || true)\n[ \"\\${pulled:-0}\" -eq 0 ] && exit 0\n\n# A pull commit should also delete the WP bodies from BACKLOG.md.\nbacklog_deletions=$(git show --format= HEAD -- BACKLOG.md 2>/dev/null | grep -cE '^-[^-]' || true)\nif [ \"\\${backlog_deletions:-0}\" -eq 0 ]; then\n jq -n --arg ctx \"Sprint-open hygiene: the commit you just made adds WP checkbox(es) to '## Current Sprint' but deletes nothing from BACKLOG.md. Pulling a WP means MOVING it — delete its entry from BACKLOG.md in the same commit. If these WPs came from BACKLOG.md, scrub it now and run 'git commit --amend'. If this is a fresh-scope sprint with no backlog pulls, ignore this.\" '{hookSpecificOutput:{hookEventName:\"PostToolUse\",additionalContext:$ctx}}'\nfi\n\nexit 0\n`;\n\nexport const WORKFLOW_CHECK = `#!/usr/bin/env bash\n# Warns on BACKLOG.md / TASKS.md drift. Non-blocking (always exits 0).\n# Warnings are emitted as PostToolUse additionalContext JSON so they reach\n# the model — bare stdout on PostToolUse only reaches the transcript view.\n# 1. A WP entry lives in a BACKLOG.md P-section AND in '## Current Sprint'\n# (violates move-not-copy). Changelog + \"Depends on:\" mentions are fine.\n# 2. TASKS.md longer than 80 lines.\n# 3. '## Current Sprint' has more than 15 items (hard split trigger).\n# 4. '## Session Log' has more than 3 entries.\n# 5. A pulled WP's \"Depends on:\" dependency still sits in a P-section.\n\nset -u\ncommand -v jq >/dev/null 2>&1 || exit 0\nfp=$(jq -r '.tool_input.file_path // empty' 2>/dev/null)\n\n# Only act on edits to BACKLOG.md or TASKS.md.\necho \"$fp\" | grep -qE '(^|/)(BACKLOG|TASKS)\\\\.md$' || exit 0\n\nwarnings=\"\"\nwarn() { warnings=\"\\${warnings}\\$*\n\"; }\n\n# WP IDs that live as entries in BACKLOG P-sections (not Changelog, not Depends-on).\nbacklog_ids=\"\"\nif [ -f BACKLOG.md ]; then\n backlog_ids=$(awk '/^## P[0-3]/{f=1;next} /^## /{f=0} f' BACKLOG.md 2>/dev/null | grep -E '^### ' | grep -oE 'WP-[0-9]{3,}' | sort -u || true)\nfi\n\n# WP IDs in the Current Sprint checklist.\nsprint_ids=\"\"\nif [ -f TASKS.md ]; then\n sprint_ids=$(awk '/^## Current/{f=1;next} /^## /{f=0} f' TASKS.md 2>/dev/null | grep -oE 'WP-[0-9]{3,}' | sort -u || true)\nfi\n\n# 1. Same WP as a live entry in both files.\nif [ -n \"$backlog_ids\" ] && [ -n \"$sprint_ids\" ]; then\n dupes=$(comm -12 <(printf '%s\\\\n' \"$backlog_ids\") <(printf '%s\\\\n' \"$sprint_ids\"))\n if [ -n \"$dupes\" ]; then\n warn \"Workflow bug: WP present in BOTH a BACKLOG.md P-section and '## Current Sprint' (violates move-not-copy — see .claude/rules/workflow.md): $(printf '%s ' $dupes)— move each listed WP to exactly one file.\"\n fi\nfi\n\nif [ -f TASKS.md ]; then\n # 2. TASKS.md length.\n tasks_lines=$(wc -l < TASKS.md 2>/dev/null | tr -d ' ')\n if [ \"\\${tasks_lines:-0}\" -gt 80 ]; then\n warn \"TASKS.md is $tasks_lines lines — should stay under 80. Prune Completed Sprints or Session Log.\"\n fi\n\n # 3. Current Sprint size (hard trigger; the soft target is 3-6).\n current_count=$(awk '/^## Current/{flag=1; next} /^## /{flag=0} flag' TASKS.md 2>/dev/null | grep -cE '^[[:space:]]*- \\\\[[ xX]\\\\]' || true)\n if [ \"\\${current_count:-0}\" -gt 15 ]; then\n warn \"'## Current Sprint' has $current_count items — split the sprint (see .claude/rules/workflow.md).\"\n fi\n\n # 4. Session Log size.\n log_count=$(awk '/^## Session Log/{flag=1; next} /^## /{flag=0} flag' TASKS.md 2>/dev/null | grep -cE '^- \\\\*\\\\*' || true)\n if [ \"\\${log_count:-0}\" -gt 3 ]; then\n warn \"'## Session Log' has $log_count entries — keep to 3 max.\"\n fi\nfi\n\n# 5. Dependency-aware pulls: the pulled WP's 7-field body left BACKLOG.md, but\n# HEAD's copy (pre-pull) still records its \"Depends on:\" line.\nif [ -n \"$sprint_ids\" ] && git rev-parse --verify HEAD >/dev/null 2>&1; then\n for wp in $sprint_ids; do\n deps=$( { git show HEAD:BACKLOG.md 2>/dev/null; cat BACKLOG.md 2>/dev/null; } | awk -v id=\"$wp\" '$0 ~ \"^### \"id\" \"{f=1;next} /^### /{f=0} f && /Depends on:/{print}' | grep -oE 'WP-[0-9]{3,}' | sort -u || true)\n for dep in $deps; do\n if printf '%s\\\\n' \"$backlog_ids\" | grep -qx \"$dep\"; then\n warn \"$wp was pulled into the sprint but its dependency $dep is still in BACKLOG.md — pull $dep too, or move $wp back until $dep ships.\"\n fi\n done\n done\nfi\n\nif [ -n \"$warnings\" ]; then\n jq -n --arg ctx \"$warnings\" '{hookSpecificOutput:{hookEventName:\"PostToolUse\",additionalContext:$ctx}}'\nfi\nexit 0\n`;\n\n// ─── Shared hook command strings (single source: init generator + doctor fixers) ───\n\n/**\n * When every Current Sprint checkbox flips to [x], nudge the model to run\n * /code-review before the closing commit. Emitted as additionalContext JSON —\n * bare PostToolUse stdout never reaches the model. Counts are anchored so\n * placeholder comments containing \"- [ ]\" don't register as open WPs.\n */\nexport const SPRINT_COMPLETE_NUDGE = `fp=${jqField(\"file_path\")}; echo \"$fp\" | grep -q TASKS.md || exit 0; section=$(sed -n '/^## Current/,/^## /p' TASKS.md 2>/dev/null); [ -z \"$section\" ] && exit 0; unchecked=$(echo \"$section\" | grep -cE '^[[:space:]]*- \\\\[ \\\\]' || true); checked=$(echo \"$section\" | grep -cE '^[[:space:]]*- \\\\[[xX]\\\\]' || true); [ \"$unchecked\" -eq 0 ] && [ \"$checked\" -gt 0 ] && jq -n --arg ctx 'Sprint complete - all Current Sprint tasks are checked off. Run /code-review on the sprint diff (base: the last chore(sprint- commit)) and fix Critical/Important findings before the closing commit. Skip if the sprint was trivial (docs/config only).' '{hookSpecificOutput:{hookEventName:\"PostToolUse\",additionalContext:$ctx}}'; exit 0`;\n\nexport const WORKFLOW_CHECK_WRAPPER = \"bash .claude/hooks/workflow-check.sh; exit 0\";\nexport const SPRINT_OPEN_WRAPPER = \"bash .claude/hooks/sprint-open-check.sh; exit 0\";\nexport const SPRINT_SIZE_WRAPPER = \"bash .claude/hooks/sprint-size-check.sh TASKS.md 2>/dev/null; exit 0\";\n\n/** SessionStart matcher incl. compact/clear — there is no PostCompact hook event. */\nexport const SESSION_START_MATCHER = \"startup|resume|compact|clear\";\n\nexport interface InstalledScripts {\n readonly sizePath: string;\n readonly openPath: string;\n}\n\nexport async function writeSprintHygieneScripts(root: string): Promise<InstalledScripts> {\n const hooksDir = join(root, \".claude\", \"hooks\");\n await mkdir(hooksDir, { recursive: true });\n const sizePath = join(hooksDir, \"sprint-size-check.sh\");\n const openPath = join(hooksDir, \"sprint-open-check.sh\");\n await writeFile(sizePath, SPRINT_SIZE_CHECK);\n await writeFile(openPath, SPRINT_OPEN_CHECK);\n await chmod(sizePath, 0o755);\n await chmod(openPath, 0o755);\n return { sizePath, openPath };\n}\n\nexport async function writeWorkflowCheckScript(root: string): Promise<string> {\n const hooksDir = join(root, \".claude\", \"hooks\");\n await mkdir(hooksDir, { recursive: true });\n const scriptPath = join(hooksDir, \"workflow-check.sh\");\n await writeFile(scriptPath, WORKFLOW_CHECK);\n await chmod(scriptPath, 0o755);\n return scriptPath;\n}\n","/**\n * Canonical helpers for hook command strings.\n *\n * Claude Code passes hook context as JSON on stdin, NOT as env vars.\n * Reading $TOOL_INPUT_FILE_PATH or $TOOL_INPUT_COMMAND from a hook command\n * sees an empty string and the hook silently no-ops on the first guard line.\n *\n * Use jqField(\"file_path\") for single-field reads.\n * Use READ_STDIN_PREAMBLE + jqField(\"...\", \"input\") when a hook needs\n * multiple fields from the same JSON input (stdin can only be read once).\n *\n * Reference: https://code.claude.com/docs/en/hooks.md\n * \"For command hooks, input arrives on stdin.\"\n * \"command=$(jq -r '.tool_input.command' < /dev/stdin)\"\n */\n\nimport { execFileSync } from \"node:child_process\";\n\nexport type ToolInputField = \"file_path\" | \"command\" | \"new_text\" | \"content\";\n\nexport function jqField(field: ToolInputField, fromVar?: string): string {\n if (fromVar) {\n return `$(echo \"$${fromVar}\" | jq -r '.tool_input.${field} // empty' 2>/dev/null)`;\n }\n return `$(jq -r '.tool_input.${field} // empty' 2>/dev/null)`;\n}\n\nexport const READ_STDIN_PREAMBLE = `input=$(cat 2>/dev/null)`;\n\nconst ENV_VAR_PATTERN = /\\$\\{?TOOL_INPUT_(FILE_PATH|COMMAND|NEW_TEXT|CONTENT)/;\n\nexport function hasEnvVarHookPattern(commandString: string): boolean {\n return ENV_VAR_PATTERN.test(commandString);\n}\n\nlet jqChecked: boolean | null = null;\n\n/** All generated hooks parse stdin via jq — without it every guard silently no-ops. */\nexport function isJqAvailable(): boolean {\n if (jqChecked !== null) return jqChecked;\n try {\n execFileSync(\"jq\", [\"--version\"], { stdio: \"ignore\" });\n jqChecked = true;\n } catch {\n jqChecked = false;\n }\n return jqChecked;\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { log } from \"../../lib/output.js\";\nimport { fileExists } from \"../../lib/fs-utils.js\";\nimport { generateWorkflowRule } from \"../init/generators/workflow-rule.js\";\nimport { generateHooksRule } from \"../init/generators/hooks-rule.js\";\nimport { generateVerificationRule } from \"../init/generators/verification-rule.js\";\nimport { generateReviewerAgent } from \"../init/generators/agent-reviewer.js\";\nimport {\n STALE_SWARM_PHRASE,\n SWARM_PHRASE_REPLACEMENT,\n} from \"../../lib/sections.js\";\n\nexport async function createWorkflowRule(root: string): Promise<boolean> {\n const rulesDir = join(root, \".claude\", \"rules\");\n const workflowPath = join(rulesDir, \"workflow.md\");\n if (await fileExists(workflowPath)) return false;\n\n await mkdir(rulesDir, { recursive: true });\n await writeFile(workflowPath, generateWorkflowRule());\n log.success(\n \"Created .claude/rules/workflow.md (path-scoped BACKLOG/TASKS workflow rules)\",\n );\n return true;\n}\n\nexport async function createReviewerAgent(root: string): Promise<boolean> {\n const agentsDir = join(root, \".claude\", \"agents\");\n const agentPath = join(agentsDir, \"code-reviewer.md\");\n if (await fileExists(agentPath)) return false;\n\n await mkdir(agentsDir, { recursive: true });\n await writeFile(agentPath, generateReviewerAgent());\n log.success(\n \"Created .claude/agents/code-reviewer.md (fresh-context independent reviewer)\",\n );\n return true;\n}\n\n/** Overwrite a versioned, launchpad-authored workflow.md with the latest template. */\nexport async function updateWorkflowRule(root: string): Promise<boolean> {\n const workflowPath = join(root, \".claude\", \"rules\", \"workflow.md\");\n const content = await readFile(workflowPath, \"utf-8\").catch(() => null);\n if (content === null) return false;\n // Only overwrite files carrying our version marker — never user-authored rules.\n if (!/<!-- lp-workflow-version: \\d+ -->/.test(content)) return false;\n\n await writeFile(workflowPath, generateWorkflowRule());\n log.success(\"Updated .claude/rules/workflow.md to the latest version\");\n return true;\n}\n\n/** Replace the known-stale 'Agent tool' phrase in CLAUDE.md; custom content is left alone. */\nexport async function fixStaleSwarmPhrase(root: string): Promise<boolean> {\n const claudeMdPath = join(root, \"CLAUDE.md\");\n const content = await readFile(claudeMdPath, \"utf-8\").catch(() => null);\n if (content === null || !content.includes(STALE_SWARM_PHRASE)) return false;\n\n await writeFile(\n claudeMdPath,\n content.replaceAll(STALE_SWARM_PHRASE, SWARM_PHRASE_REPLACEMENT),\n );\n log.success(\n \"Modernized Stop-and-Swarm wording (Agent tool → Task tool subagents)\",\n );\n return true;\n}\n\nexport async function createHooksRule(root: string): Promise<boolean> {\n const rulesDir = join(root, \".claude\", \"rules\");\n const hooksPath = join(rulesDir, \"hooks.md\");\n if (await fileExists(hooksPath)) return false;\n\n await mkdir(rulesDir, { recursive: true });\n await writeFile(hooksPath, generateHooksRule());\n log.success(\n \"Created .claude/rules/hooks.md (path-scoped hook authoring rules)\",\n );\n return true;\n}\n\nexport async function createVerificationRule(root: string): Promise<boolean> {\n const rulesDir = join(root, \".claude\", \"rules\");\n const verificationPath = join(rulesDir, \"verification.md\");\n if (await fileExists(verificationPath)) return false;\n\n await mkdir(rulesDir, { recursive: true });\n await writeFile(verificationPath, generateVerificationRule());\n log.success(\n \"Created .claude/rules/verification.md (evidence-before-assertion discipline)\",\n );\n return true;\n}\n\n/** Overwrite a versioned, launchpad-authored verification.md with the latest template. */\nexport async function updateVerificationRule(root: string): Promise<boolean> {\n const verificationPath = join(root, \".claude\", \"rules\", \"verification.md\");\n const content = await readFile(verificationPath, \"utf-8\").catch(() => null);\n if (content === null) return false;\n // Only overwrite files carrying our version marker — never user-authored rules.\n if (!/<!-- lp-verification-version: \\d+ -->/.test(content)) return false;\n\n await writeFile(verificationPath, generateVerificationRule());\n log.success(\"Updated .claude/rules/verification.md to the latest version\");\n return true;\n}\n\ntype MemoryBlock = {\n readonly startIdx: number;\n readonly endIdx: number;\n readonly tagged: boolean;\n};\n\nfunction isMemoryHeading(line: string): boolean {\n return /^## Memory( \\(agentic-memory\\))?\\s*$/.test(line);\n}\n\nfunction findMemoryBlocks(lines: readonly string[]): readonly MemoryBlock[] {\n const blocks: MemoryBlock[] = [];\n for (let i = 0; i < lines.length; i++) {\n if (!isMemoryHeading(lines[i])) continue;\n let end = lines.length;\n for (let j = i + 1; j < lines.length; j++) {\n if (/^## /.test(lines[j])) {\n end = j;\n break;\n }\n }\n blocks.push({\n startIdx: i,\n endIdx: end,\n tagged: lines[i].includes(\"(agentic-memory)\"),\n });\n i = end - 1;\n }\n return blocks;\n}\n\n/**\n * Collapse duplicate `## Memory` / `## Memory (agentic-memory)` sections in CLAUDE.md.\n * Keeps the first `## Memory (agentic-memory)` block (canonical), or the first plain\n * `## Memory` block if no tagged one exists. Drops all subsequent memory sections.\n */\nexport async function collapseMemoryHeadings(root: string): Promise<boolean> {\n const claudeMdPath = join(root, \"CLAUDE.md\");\n let content: string;\n try {\n content = await readFile(claudeMdPath, \"utf-8\");\n } catch {\n return false;\n }\n\n const lines = content.split(\"\\n\");\n const blocks = findMemoryBlocks(lines);\n if (blocks.length <= 1) return false;\n\n const keeper = blocks.find((b) => b.tagged) ?? blocks[0];\n const droppedByStart = new Map<number, MemoryBlock>(\n blocks.filter((b) => b !== keeper).map((b) => [b.startIdx, b]),\n );\n\n const kept: string[] = [];\n let skipUntil = -1;\n for (let i = 0; i < lines.length; i++) {\n if (i < skipUntil) continue;\n const dropped = droppedByStart.get(i);\n if (dropped) {\n skipUntil = dropped.endIdx;\n continue;\n }\n kept.push(lines[i]);\n }\n\n // Canonicalize the kept heading to `## Memory (agentic-memory)`.\n const canonical = kept.map((line) =>\n /^## Memory\\s*$/.test(line) ? \"## Memory (agentic-memory)\" : line,\n );\n\n await writeFile(claudeMdPath, canonical.join(\"\\n\"));\n log.success(\n `Collapsed ${blocks.length - 1} duplicate ## Memory section(s) in CLAUDE.md`,\n );\n return true;\n}\n","export const WORKFLOW_RULE_VERSION = 2;\n\nexport function generateWorkflowRule(): string {\n return `---\npaths: [\"BACKLOG.md\", \"TASKS.md\"]\n---\n\n# Backlog → Tasks → Sprint Workflow Rules\n\n<!-- lp-workflow-version: ${WORKFLOW_RULE_VERSION} -->\n\nThese rules apply whenever editing \\`BACKLOG.md\\` or \\`TASKS.md\\`. The workflow is load-bearing — drift here breaks sprint integrity.\n\n## The single rule that makes everything else work\n\n**A work package (WP) lives in exactly one of \\`BACKLOG.md\\` or \\`TASKS.md\\` at any time.**\n\n- Pulled into a sprint → move (delete from BACKLOG.md, add to TASKS.md under \\`## Current Sprint\\`) in a single edit.\n- Sprint closed → the WP leaves TASKS.md entirely (summarized into \\`## Completed Sprints\\`) and does not return to the backlog.\n- A WP entry appearing in both files at once = bug. \\`workflow-check.sh\\` injects a warning into context when it sees one (Changelog and \\`Depends on:\\` mentions are fine).\n\n## WP IDs\n\n- Format: \\`WP-NNN\\` (three digits, zero-padded; grows to four digits past WP-999).\n- Minted on first entry to \\`BACKLOG.md\\`; log every mint in \\`## Changelog\\`: \\`YYYY-MM-DD: WP-NNN added (P1)\\`.\n- Never reused, never renamed.\n- To find the highest used ID before minting: \\`grep -ohE 'WP-[0-9]+' BACKLOG.md TASKS.md | sort -V | tail -1\\`.\n\n## BACKLOG.md structure (mandatory sections, in order)\n\n1. Header + rules comment block\n2. \\`## Priority definitions\\` table\n3. \\`## Work package template\\` (the canonical format)\n4. \\`## P0 — Next sprint\\`\n5. \\`## P1 — Soon (within 2–3 sprints)\\`\n6. \\`## P2 — Post-MVP / nice-to-have\\`\n7. \\`## P3 — Parked\\`\n8. \\`## Changelog\\`\n\n### Every WP entry must include\n\n- \\`Priority:\\` exactly one of P0/P1/P2/P3\n- \\`Proposed:\\` ISO date (YYYY-MM-DD)\n- \\`Stories / Docs:\\` spec references, issues, or empty\n- \\`Depends on:\\` WP IDs or empty\n- \\`Estimate:\\` one of XS/S/M/L/XL (XL must be decomposed before pulling)\n- \\`Trigger to pull:\\` what event promotes this to an active sprint\n- \\`Definition of done:\\` concrete acceptance criteria\n- One-paragraph description\n\n### Priority discipline\n\n- P0 items are for the next sprint. If P0 is empty at sprint start, pull the top P1.\n- P1 → P0 promotion happens during sprint wrap-up, not mid-sprint.\n- P2 items get a monthly review. P3 items get a quarterly review and are deleted if still untouched.\n- Stale P0 items (>2 weeks without movement) are a flag: either pull or demote.\n\n### Changelog discipline\n\n- Every WP mint, promotion, demotion, or deletion gets a one-line entry with the date.\n- A backlog audit that finds no changelog entries for 30+ days = staleness; force a review.\n\n## TASKS.md structure (mandatory sections, in order)\n\n1. Header + rules comment\n2. \\`## Current Sprint\\`\n3. \\`## Completed Sprints\\`\n4. \\`## Session Log\\`\n\n### \\`## Current Sprint\\` discipline\n\n- Contains ONLY the active sprint's WPs. Empty between sprints.\n- Format: \\`- [ ] WP-NNN — short title\\` (checkbox + WP ID + title from backlog).\n- Each pulled WP becomes one checklist item. Sub-tasks nest with two-space indent, still checkbox.\n- New ideas that surface mid-sprint go to \\`BACKLOG.md\\`, never appended here.\n\n### \\`## Completed Sprints\\` discipline\n\n- One line per sprint. Format: \\`- **SN**: one-sentence outcome + key metric if any.\\`\n- Never a wall of text. Detail lives in git history (or your review file).\n\n### \\`## Session Log\\` discipline\n\n- Max 3 entries, most recent 3 sessions only.\n- Each entry: \\`- **YYYY-MM-DD (optional window):** what changed this session + what's next.\\`\n- Older entries deleted, not archived — they're in git history if needed.\n\n### Size discipline\n\n- Whole file stays under 80 lines.\n- Aim for 3-6 WPs per sprint (soft target — \\`sprint-size-check.sh\\` nudges at session start).\n- If \\`## Current Sprint\\` exceeds 15 checkboxes, the sprint is too big — split it (hard trigger; \\`workflow-check.sh\\` warns).\n\n## Sprint lifecycle (the exact edit sequence)\n\n### Starting a sprint (one session, one commit)\n\n1. Pick top-priority WPs from \\`BACKLOG.md\\` (P0 first).\n2. **Same edit:** delete them from \\`BACKLOG.md\\`, add them to \\`TASKS.md ## Current Sprint\\`.\n3. Update \\`BACKLOG.md ## Changelog\\`: \\`YYYY-MM-DD: WP-NNN pulled into Sprint SN\\`.\n4. Write the sprint plan (outline approach, success criteria, tests to add).\n5. For hard-TDD surfaces (see \"Testing Discipline\" in \\`.claude/rules/conventions.md\\`), write the test spec **before** implementation.\n6. Commit the pull + plan together: \\`chore(sprint-N): pull WP-NNN into sprint + plan\\`.\n\n### Closing a sprint (one session, one commit)\n\n1. All \\`## Current Sprint\\` items checked off, or explicitly moved back to backlog with rationale.\n2. Review the sprint diff: find the base with \\`git log --grep 'chore(sprint-' -n 1 --format=%H\\`, run \\`/code-review\\` against it, and fix all Critical/Important findings. Then run the project's test and typecheck commands — both must pass.\n3. Add one-line summary to \\`## Completed Sprints\\`.\n4. Empty \\`## Current Sprint\\` back to the placeholder comment.\n5. Update \\`## Session Log\\` (prune to 3 entries).\n6. \\`BACKLOG.md ## Changelog\\`: \\`YYYY-MM-DD: Sprint SN closed. WP-NNN done.\\`\n\n## What triggers a staleness warning\n\n\\`workflow-check.sh\\` (PostToolUse on BACKLOG/TASKS edits) injects warnings into context — as \\`additionalContext\\`, so the model actually sees them — on these conditions (treat as bugs):\n\n- A WP entry lives in both a \\`BACKLOG.md\\` P-section and \\`## Current Sprint\\`.\n- \\`TASKS.md\\` exceeds 80 lines.\n- \\`## Current Sprint\\` has >15 items.\n- \\`## Session Log\\` has >3 entries.\n- A pulled WP's \\`Depends on:\\` dependency still sits in a BACKLOG P-section.\n\n\\`sprint-open-check.sh\\` (PostToolUse on Bash) additionally warns after a \\`git commit\\` that pulls WPs into the sprint without deleting anything from \\`BACKLOG.md\\` — fix with \\`git commit --amend\\` before pushing.\n\n## Do not\n\n- Don't append to \\`TASKS.md\\` without first checking \\`BACKLOG.md\\` for the WP — silent duplication breaks the source-of-truth rule.\n- Don't leave \\`## Current Sprint\\` populated between sprints. An empty sprint section is how you know the last sprint closed cleanly.\n- Don't invent ad-hoc WP formats. Use the template or update the template — never both.\n- Don't rewrite \\`## Completed Sprints\\` into prose. One line each. Forever.\n- Don't put anything in \\`TASKS.md\\` that hasn't passed through \\`BACKLOG.md\\` first. Ideas → backlog → sprint. No shortcuts.\n`;\n}\n","export const HOOKS_RULE_VERSION = 1;\n\nexport function generateHooksRule(): string {\n return `---\npaths: [\".claude/settings.json\", \".claude/settings.local.json\"]\n---\n\n# Claude Code Hook Authoring Rules\n\n<!-- lp-hooks-version: ${HOOKS_RULE_VERSION} -->\n\nApplies to every hook entry in \\`.claude/settings.json\\` and \\`.claude/settings.local.json\\`. Hooks are the project's automated safety net. Getting the API wrong silently disables the protection without any error. **A broken hook is worse than no hook because it gives false confidence.**\n\nReference: https://code.claude.com/docs/en/hooks\n\n## Anatomy of a hook entry\n\n\\`\\`\\`json\n{\n \"hooks\": {\n \"<EventName>\": [\n {\n \"matcher\": \"<ToolMatcher>\",\n \"hooks\": [\n { \"type\": \"command\", \"command\": \"<shell-string>\" }\n ]\n }\n ]\n }\n}\n\\`\\`\\`\n\n- \\`EventName\\`: \\`SessionStart\\`, \\`SessionEnd\\`, \\`PreToolUse\\`, \\`PostToolUse\\`, \\`PostToolUseFailure\\`, \\`UserPromptSubmit\\`, \\`Stop\\`, \\`PermissionRequest\\`, \\`PreCompact\\`, \\`PostCompact\\`. PostCompact is side-effect-only (stdout is never injected) — to re-inject context after compaction, use SessionStart with matcher \\`compact\\`.\n- \\`matcher\\`: a regex-style string matching tool names (e.g. \\`Bash\\`, \\`Read|Write|Edit\\`). Empty string matches all tools for the event. For SessionStart use \\`startup\\`, \\`resume\\`, \\`clear\\`, or \\`compact\\`.\n- \\`hooks\\` array: every entry runs in parallel when the matcher fires. Identical command strings are deduplicated automatically.\n\n## Input — JSON on stdin, NOT env vars\n\nThe hook receives a JSON payload on stdin. **There are no \\`TOOL_INPUT_*\\` environment variables in current Claude Code.** A hook that does \\`cmd=\"$TOOL_INPUT_COMMAND\"\\` reads an empty string and silently no-ops. This is the single most common authoring bug.\n\nCanonical extraction:\n\n\\`\\`\\`bash\nfp=$(jq -r '.tool_input.file_path // empty' 2>/dev/null) # PreToolUse Read|Write|Edit\ncmd=$(jq -r '.tool_input.command // empty' 2>/dev/null) # PreToolUse Bash\nnew=$(jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null) # PostToolUse Edit|Write\n\\`\\`\\`\n\nTop-level keys you can read: \\`session_id\\`, \\`transcript_path\\`, \\`cwd\\`, \\`permission_mode\\`, \\`hook_event_name\\`, \\`tool_name\\`, \\`tool_input\\`, \\`tool_use_id\\`. \\`PostToolUse\\` adds \\`tool_response\\`.\n\n\\`jq\\` is a project-level requirement. Install via \\`brew install jq\\` (macOS) or your distro's package manager.\n\n## Exit codes — 2 blocks, 1 does not\n\n| Exit code | Effect |\n|---|---|\n| \\`0\\` | Allow the action. Hook stdout becomes context (SessionStart) or is informational (PostToolUse). |\n| \\`2\\` | Block the action. Hook stderr is fed back to Claude as the error reason. |\n| any other non-zero (\\`1\\`, \\`127\\`, …) | Treated as a non-blocking hook error. **The action proceeds anyway.** |\n\n\\`exit 1\\` does NOT block. If the hook is meant to enforce a policy, it must end in \\`exit 2\\`.\n\nBlock reasons go to **stderr** (\\`echo '...' >&2\\`), not stdout. Stdout is ignored when exit code is 2 unless the hook returns the JSON envelope (see \"Richer control\" below).\n\n## Output — stderr for blocks, stdout for warnings\n\n\\`\\`\\`bash\n# Blocking: stderr + exit 2\necho 'BLOCKED: <reason shown to Claude>' >&2\nexit 2\n\n# Informational warning that does not block: stdout + exit 0\necho 'WARNING: <message printed to user>'\nexit 0\n\\`\\`\\`\n\nRicher control (only use when the simple form is insufficient):\n\n\\`\\`\\`bash\njq -n '{\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n permissionDecisionReason: \"<reason>\"\n }\n}'\nexit 0\n\\`\\`\\`\n\n## Multi-hook same matcher — combine into ONE entry\n\nIf two top-level entries share the same matcher (e.g. two \\`PreToolUse\\` entries both with \\`matcher: \"Bash\"\\`), behavior is undefined: in practice the second entry can fail to fire. **Always combine commands for the same matcher into a single entry's \\`hooks\\` array.**\n\nWrong:\n\n\\`\\`\\`jsonc\n\"PreToolUse\": [\n { \"matcher\": \"Bash\", \"hooks\": [{ \"type\": \"command\", \"command\": \"<destructive-guard>\" }] },\n { \"matcher\": \"Bash\", \"hooks\": [{ \"type\": \"command\", \"command\": \"<sprint-open-check>\" }] }\n]\n\\`\\`\\`\n\nRight:\n\n\\`\\`\\`jsonc\n\"PreToolUse\": [\n {\n \"matcher\": \"Bash\",\n \"hooks\": [\n { \"type\": \"command\", \"command\": \"<destructive-guard>\" },\n { \"type\": \"command\", \"command\": \"<sprint-open-check>\" }\n ]\n }\n]\n\\`\\`\\`\n\n## Hot-reload — there is none\n\nEdits to \\`.claude/settings.json\\` or \\`.claude/settings.local.json\\` only take effect after a Claude Code session restart. Mid-session edits parse fine and persist to disk, but the running session keeps the hooks it loaded at start.\n\nWhen fixing or adding a hook:\n\n1. Edit settings.json\n2. Test the hook command in isolation (see \"Testing\" below)\n3. Restart Claude Code\n4. Verify the hook fires by triggering the conditions it watches\n\nSkipping step 3 means the new hook does not exist yet, no matter what the file says.\n\n## Testing a hook command in isolation\n\nBefore installing or restarting, verify the command works by piping a fake JSON payload to it:\n\n\\`\\`\\`bash\nHOOK=$(jq -r '.hooks.PreToolUse[<index>].hooks[<index>].command' .claude/settings.json)\necho '{\"tool_input\":{\"command\":\"git push --force\"}}' | bash -c \"$HOOK\"\necho \"exit=$?\"\n\\`\\`\\`\n\nExpected for a correctly-blocking hook: stderr contains the BLOCKED reason, \\`exit=2\\`. If you see \\`exit=0\\` here, the hook will not block in production either.\n\nFor PostToolUse hooks that read file paths or content, build the JSON to mirror the tool you're matching:\n\n\\`\\`\\`bash\necho '{\"tool_input\":{\"file_path\":\"docs/architecture.md\",\"new_string\":\"...\"}}' | bash -c \"$HOOK\"\n\\`\\`\\`\n\n## Canonical templates\n\n### PreToolUse Bash gate (block on regex match)\n\n\\`\\`\\`bash\ncmd=$(jq -r '.tool_input.command // empty' 2>/dev/null); echo \"$cmd\" | grep -qE '<your-pattern>' || exit 0; echo 'BLOCKED: <reason>' >&2; exit 2\n\\`\\`\\`\n\n**Do not anchor the pattern with \\`^[[:space:]]*\\`** when you want to catch chained commands. The hook receives the entire shell command string verbatim, so an anchored pattern silently misses commands like \\`git status && git push\\`. Use \\`(^|[^[:alnum:]])<token>([[:space:]]|$)\\` to match the token at start-of-line OR after a non-alphanumeric separator.\n\n### PreToolUse Read|Write|Edit gate (block on file-path match)\n\n\\`\\`\\`bash\nfp=$(jq -r '.tool_input.file_path // empty' 2>/dev/null); echo \"$fp\" | grep -qE '<your-pattern>' || exit 0; echo 'BLOCKED: <reason>' >&2; exit 2\n\\`\\`\\`\n\n### PostToolUse informational warner (never blocks; just prints)\n\n\\`\\`\\`bash\nfp=$(jq -r '.tool_input.file_path // empty' 2>/dev/null); echo \"$fp\" | grep -qE '<your-pattern>' || exit 0; echo '<warning text>'; exit 0\n\\`\\`\\`\n\nPostToolUse blocking (exit 2) is supported but rare. By the time PostToolUse fires, the file write has already happened. Almost always you want exit 0 with a stdout message.\n\n### SessionStart context injection\n\n\\`\\`\\`bash\ncat <some-file> 2>/dev/null; exit 0\n\\`\\`\\`\n\nOutput goes into the session's context. Always exit 0; SessionStart blocking is not a thing.\n\n## Adding a new hook — checklist\n\n- [ ] Identify the event and matcher you actually need (\\`PreToolUse\\` for blocking before, \\`PostToolUse\\` for after-the-fact warnings).\n- [ ] Read the input via stdin JSON with \\`jq\\`, **not env vars**.\n- [ ] If it blocks: send reason to stderr, end with \\`exit 2\\`. If it warns: stdout, end with \\`exit 0\\`.\n- [ ] If a hook for the same matcher already exists, add your command to its existing \\`hooks\\` array — do NOT create a second entry with the same matcher.\n- [ ] Test the command in isolation by piping a fake JSON payload (see \"Testing\" above) — verify the exit code matches your intent.\n- [ ] Restart Claude Code.\n- [ ] Verify the hook fires under the conditions it watches and does not fire under benign conditions.\n\n## Do not\n\n- Don't reference \\`$TOOL_INPUT_COMMAND\\`, \\`$TOOL_INPUT_FILE_PATH\\`, \\`$TOOL_INPUT_NEW_TEXT\\`, or any other \\`TOOL_INPUT_*\\` env var. They do not exist; the hook silently no-ops.\n- Don't \\`exit 1\\` to block. It is silently non-blocking. Use \\`exit 2\\`.\n- Don't echo the block reason to stdout when exiting 2. Stdout is ignored in that case; only stderr reaches Claude.\n- Don't create a second top-level entry with a matcher that already has an entry. Combine commands in the existing entry's \\`hooks\\` array.\n- Don't expect mid-session settings.json edits to take effect. Restart is required.\n- Don't ship a hook without isolation-testing the command first. A silent no-op is worse than no hook.\n- Don't put long debug logging into a production hook. If you need diagnostics during development, write to \\`/tmp/<name>.log\\` and remove the line before commit.\n`;\n}\n","export const VERIFICATION_RULE_VERSION = 1;\n\nexport function generateVerificationRule(): string {\n return `# Verification Rules\n\n<!-- lp-verification-version: ${VERIFICATION_RULE_VERSION} -->\n\nThese rules govern every claim of \"done\", \"fixed\", \"passing\", or \"works\". A claim without evidence is a defect, no matter how good the code is.\n\n## Evidence before assertion\n\n- Never claim done/fixed/passing without having run the thing this session and quoting the output. The claim and its evidence travel together: \"Done — 14/14 tests pass (output below)\", never a bare \"done\".\n- Verify the behavior, not the build. Compiling is not working; typechecking is not working. Exercise the changed flow end-to-end: run the command, hit the endpoint, click the path.\n- For bug fixes: reproduce the failure FIRST and capture the exact error. Then fix, then re-run the original reproduction AND the surrounding tests. If you cannot explain the root cause, you have hidden the bug, not fixed it.\n- Test the failure case, not just the happy path: feed the change the input that used to break it and confirm it now lands safely.\n\n## Label your claims\n\nSort every load-bearing statement into one of three buckets, and say which out loud:\n\n- **verified** — you read it or ran it this session\n- **inferred** — follows logically from verified facts; state the chain\n- **assumed** — plausible from prior knowledge; check it before building on it\n\nNever let an assumption silently graduate into a fact. APIs, config keys, CLI flags, and package names cited from memory are the #1 hallucination vector — open the real source or current docs before citing them.\n\n## When you can't verify\n\n- If a step cannot be run (missing env, no credentials, no test data), the result is **done-with-gaps** — name each gap explicitly. Never round done-with-gaps up to done.\n- Report failure plainly. Failing tests, skipped steps, and partial work get named with the output shown. \"2 failures remain, here's the state\" preserves trust; a false \"all green\" destroys it.\n\n## End-of-turn check\n\nBefore ending a turn, re-read your last paragraph. If it is a promise (\"I'll…\", \"next I would…\"), a plan, or a question you could answer yourself — do that work now, then end. A turn ends on delivered results, not intentions.\n`;\n}\n","export const REVIEWER_AGENT_VERSION = 1;\n\n/**\n * Plugin-free independent code reviewer, generated into .claude/agents/.\n * Fresh context + read-only tools = a reviewer that can't rationalize its own\n * code. Referenced by the Sprint Reviews section as the second-pass option.\n */\nexport function generateReviewerAgent(): string {\n return `---\nname: code-reviewer\ndescription: Independent, fresh-context review of a diff. Use PROACTIVELY before sprint-ending commits. Pass base and head SHAs (find the base with \\`git log --grep 'chore(sprint-' -n 1 --format=%H\\`).\ntools: Read, Glob, Grep, Bash\n---\n\n<!-- lp-reviewer-version: ${REVIEWER_AGENT_VERSION} -->\n\nYou are an independent senior code reviewer. You did NOT write this code —\nreview it with fresh eyes and no attachment to the choices made.\n\n## Input\n\nBase and head SHAs (or a branch/range). If none given, review the working\ntree against HEAD.\n\n## Process\n\n1. \\`git diff --stat <base>..<head>\\` for the shape, then read the full diff.\n2. Read surrounding source for anything the diff touches — a hunk that looks\n fine in isolation can break an invariant defined two functions up.\n3. For each suspected bug, verify against the actual code before reporting —\n no findings from pattern-matching alone.\n4. Check: correctness, security (injection, secrets, permissions), error\n handling, convention violations (see CLAUDE.md and .claude/rules/), dead\n code, debug artifacts, missing or weakened tests.\n\n## Output (exactly these sections)\n\n- **Strengths** — what is genuinely good; be brief.\n- **Critical** — bugs, security holes, data loss. Must be fixed before commit.\n- **Important** — incorrect edge cases, convention breaks, silent failures.\n Must be fixed before commit.\n- **Minor** — polish; may be deferred to the backlog.\n- **Assessment** — 2-3 sentences: ship, fix-then-ship, or rethink.\n\nFor every Critical/Important finding give file:line and a concrete failure\nscenario (inputs/state → wrong behavior). Do not pad: an empty Critical\nsection is a valid, good result. Never soften a finding because the fix is\ninconvenient.\n`;\n}\n","import { addHookToSettings } from \"../../lib/hook-builder.js\";\nimport { readSettingsJson, writeSettingsJson } from \"../../lib/settings.js\";\nimport { log } from \"../../lib/output.js\";\nimport { SESSION_START_MATCHER } from \"../../lib/hook-scripts.js\";\nimport { jqField } from \"../../lib/hook-input.js\";\nimport type { DetectedProject } from \"../../types/index.js\";\n\nconst FORMATTERS: Record<string, { extensions: string[]; command: string }> = {\n TypeScript: { extensions: [\"ts\", \"tsx\"], command: \"npx prettier --write\" },\n JavaScript: { extensions: [\"js\", \"jsx\"], command: \"npx prettier --write\" },\n Python: { extensions: [\"py\"], command: \"ruff format\" },\n Go: { extensions: [\"go\"], command: \"gofmt -w\" },\n Rust: { extensions: [\"rs\"], command: \"rustfmt\" },\n Ruby: { extensions: [\"rb\"], command: \"rubocop -A\" },\n PHP: { extensions: [\"php\"], command: \"vendor/bin/pint\" },\n};\n\nexport async function addEnvProtectionHook(root: string): Promise<boolean> {\n return addHookToSettings(root, \"PreToolUse\", \".env\", {\n matcher: \"Read|Write|Edit\",\n hooks: [{\n type: \"command\",\n command: `fp=${jqField(\"file_path\")}; echo \"$fp\" | grep -qE '\\\\.(env|env\\\\..*)$' && ! echo \"$fp\" | grep -q '.env.example' && { echo 'BLOCKED: .env files contain secrets' >&2; exit 2; }; exit 0`,\n }],\n }, \"Added .env file protection hook (PreToolUse)\");\n}\n\nexport async function addAutoFormatHook(root: string, detected: DetectedProject): Promise<boolean> {\n if (!detected.language) return false;\n const config = detected.language ? FORMATTERS[detected.language] : null;\n if (!config) return false;\n\n const extChecks = config.extensions.map((ext) => `[ \"$ext\" = \"${ext}\" ]`).join(\" || \");\n return addHookToSettings(root, \"PostToolUse\", \"format\", {\n matcher: \"Write|Edit\",\n hooks: [{\n type: \"command\",\n command: `fp=${jqField(\"file_path\")}; ext=\"\\${fp##*.}\"; (${extChecks}) && ${config.command} \"$fp\" 2>/dev/null; exit 0`,\n }],\n }, `Added auto-format hook (PostToolUse → ${config.command})`);\n}\n\nexport async function addForcePushProtection(root: string): Promise<boolean> {\n return addHookToSettings(root, \"PreToolUse\", \"force\", {\n matcher: \"Bash\",\n hooks: [{\n type: \"command\",\n command: `cmd=${jqField(\"command\")}; echo \"$cmd\" | grep -qE 'push.*--force|push.*-f' && { echo 'WARNING: Force push detected — this can destroy remote history' >&2; exit 2; }; exit 0`,\n }],\n }, \"Added force-push protection hook (PreToolUse → Bash)\");\n}\n\n/**\n * PostCompact is a real (side-effect) event, but its stdout is never injected\n * into context — a TASKS.md re-injection registered there does nothing.\n * Migration: remove ONLY our known TASKS.md-injection shape from PostCompact\n * (user side-effect hooks are left alone) and make sure a SessionStart entry\n * covers the compact/clear matchers instead.\n */\nexport async function migratePostCompactHook(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n\n let changed = false;\n const postCompact = (hooks.PostCompact ?? []) as Record<string, unknown>[];\n const kept = postCompact\n .map((group) => {\n const nested = (group.hooks ?? []) as Record<string, unknown>[];\n const filtered = nested.filter((h) => !String(h.command ?? \"\").includes(\"TASKS.md\"));\n if (filtered.length !== nested.length) changed = true;\n return { ...group, hooks: filtered };\n })\n .filter((group) => (group.hooks as unknown[]).length > 0);\n\n const rest: Record<string, unknown[]> = { ...hooks };\n if (kept.length > 0) rest.PostCompact = kept as unknown[];\n else delete rest.PostCompact;\n\n const withMatcher = ensureCompactMatcher(rest);\n if (withMatcher.changed) changed = true;\n if (!changed) return false;\n\n await writeSettingsJson(root, { ...settings, hooks: withMatcher.hooks });\n log.success(\"Moved TASKS.md re-injection off PostCompact (stdout not injected there) → SessionStart compact/clear matcher\");\n return true;\n}\n\nexport async function addCompactMatcherHook(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n const result = ensureCompactMatcher(hooks);\n if (!result.changed) return false;\n await writeSettingsJson(root, { ...settings, hooks: result.hooks });\n log.success(\"SessionStart matcher now covers compact/clear (session continuity after compaction)\");\n return true;\n}\n\n/** Widen the TASKS.md-injecting SessionStart entry's matcher to include compact/clear. */\nfunction ensureCompactMatcher(\n hooks: Record<string, unknown[]>,\n): { hooks: Record<string, unknown[]>; changed: boolean } {\n const sessionStart = (hooks.SessionStart ?? []) as Record<string, unknown>[];\n if (sessionStart.some((g) => String(g.matcher ?? \"\").includes(\"compact\"))) {\n return { hooks, changed: false };\n }\n const idx = sessionStart.findIndex((g) => {\n const nested = g.hooks as Record<string, unknown>[] | undefined;\n return nested?.some((h) => String(h.command ?? \"\").includes(\"TASKS.md\"));\n });\n if (idx === -1) {\n // No TASKS.md SessionStart hook to widen — add the canonical one.\n const entry = { matcher: SESSION_START_MATCHER, hooks: [{ type: \"command\", command: \"cat TASKS.md 2>/dev/null; exit 0\" }] };\n return { hooks: { ...hooks, SessionStart: [...sessionStart, entry] }, changed: true };\n }\n const widened = sessionStart.map((g, i) => (i === idx ? { ...g, matcher: SESSION_START_MATCHER } : g));\n return { hooks: { ...hooks, SessionStart: widened }, changed: true };\n}\n\nexport async function addSessionStartHook(root: string): Promise<boolean> {\n return addHookToSettings(root, \"SessionStart\", \"TASKS.md\", {\n matcher: SESSION_START_MATCHER,\n hooks: [{ type: \"command\", command: \"cat TASKS.md 2>/dev/null; exit 0\" }],\n }, \"Added SessionStart hook (injects TASKS.md at startup/resume/compact/clear)\");\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { log } from \"../../lib/output.js\";\nimport { hasEnvVarHookPattern, jqField } from \"../../lib/hook-input.js\";\nimport { readSettingsJson, writeSettingsJson } from \"../../lib/settings.js\";\nimport {\n SPRINT_COMPLETE_NUDGE,\n writeWorkflowCheckScript,\n writeSprintHygieneScripts,\n} from \"../../lib/hook-scripts.js\";\n\ninterface HookEntry {\n readonly type: \"command\";\n readonly command: string;\n}\n\ninterface HookGroup {\n readonly matcher?: string;\n readonly hooks: ReadonlyArray<HookEntry>;\n}\n\n/**\n * Rewrite an inert hook command (one that reads $TOOL_INPUT_* env vars) to the\n * canonical jq+stdin form. Returns null when the shape is unrecognized so the\n * caller can leave user customizations alone (the analyzer still warns).\n *\n * \"Rewrite\" means \"replace with the current canonical shape\". This may include\n * additional defensive guards the user did not have (e.g. `.env.example`\n * exclusion) — the canonical shape is the source of truth, not the input.\n */\nexport function rewriteEnvVarHookCommand(cmd: string): string | null {\n // Defense-in-depth: this function is gated upstream, but a direct caller\n // should never get back a \"rewritten\" version of a clean command.\n if (!hasEnvVarHookPattern(cmd)) return null;\n\n // .env file block (PreToolUse Read|Write|Edit)\n if (cmd.includes(\"BLOCKED: .env files contain secrets\")) {\n return `fp=${jqField(\"file_path\")}; echo \"$fp\" | grep -qE '\\\\.(env|env\\\\..*)$' && ! echo \"$fp\" | grep -q '.env.example' && { echo 'BLOCKED: .env files contain secrets' >&2; exit 2; }; exit 0`;\n }\n\n // Destructive bash block (PreToolUse Bash)\n if (cmd.includes(\"BLOCKED: Destructive command detected\")) {\n return `cmd=${jqField(\"command\")}; echo \"$cmd\" | grep -qE 'rm\\\\s+-rf\\\\s+/|DROP\\\\s+TABLE|DROP\\\\s+DATABASE|push.*--force|push.*-f' && { echo 'BLOCKED: Destructive command detected' >&2; exit 2; }; exit 0`;\n }\n\n // Force-push warning (PreToolUse Bash)\n if (cmd.includes(\"WARNING: Force push detected\") || cmd.includes(\"Force push detected\")) {\n return `cmd=${jqField(\"command\")}; echo \"$cmd\" | grep -qE 'push.*--force|push.*-f' && { echo 'WARNING: Force push detected — this can destroy remote history' >&2; exit 2; }; exit 0`;\n }\n\n // Sprint-complete nudge (PostToolUse Edit|Write) — emit the CURRENT canonical\n // form (additionalContext JSON, anchored counts), not the historical echo.\n if (cmd.includes(\"Sprint complete\") && cmd.includes(\"TASKS.md\")) {\n return SPRINT_COMPLETE_NUDGE;\n }\n\n // Auto-format hook (PostToolUse Write|Edit) — extract formatter + extension list from the original\n // Original shape: ext=${TOOL_INPUT_FILE_PATH##*.}; ([ \"$ext\" = \"ts\" ] || [ \"$ext\" = \"tsx\" ]) && npx prettier --write \"$TOOL_INPUT_FILE_PATH\" 2>/dev/null; exit 0\n const formatMatch = cmd.match(/ext=\\$\\{TOOL_INPUT_FILE_PATH##\\*\\.\\};\\s*\\((.+?)\\)\\s*&&\\s*(.+?)\\s*\"\\$TOOL_INPUT_FILE_PATH\"/);\n if (formatMatch) {\n const extChecks = formatMatch[1].trim();\n const formatter = formatMatch[2].trim();\n return `fp=${jqField(\"file_path\")}; ext=\"\\${fp##*.}\"; (${extChecks}) && ${formatter} \"$fp\" 2>/dev/null; exit 0`;\n }\n\n return null;\n}\n\ninterface RewriteOutcome {\n readonly settings: Record<string, unknown>;\n readonly changed: boolean;\n}\n\nfunction rewriteSettingsHooks(settings: Record<string, unknown>): RewriteOutcome {\n const hooks = settings.hooks as Record<string, ReadonlyArray<HookGroup>> | undefined;\n if (!hooks) return { settings, changed: false };\n\n let changed = false;\n const next: Record<string, ReadonlyArray<HookGroup>> = {};\n\n for (const [event, groups] of Object.entries(hooks)) {\n next[event] = groups.map((group) => ({\n ...group,\n hooks: group.hooks.map((hook) => {\n if (hook.type !== \"command\") return hook;\n if (!hasEnvVarHookPattern(hook.command)) return hook;\n const rewritten = rewriteEnvVarHookCommand(hook.command);\n if (rewritten === null) return hook;\n changed = true;\n return { ...hook, command: rewritten };\n }),\n }));\n }\n\n if (!changed) return { settings, changed: false };\n return { settings: { ...settings, hooks: next }, changed: true };\n}\n\nasync function rewriteWrapperScript(\n scriptPath: string,\n rewriter: () => Promise<unknown>,\n): Promise<boolean> {\n let content: string;\n try {\n content = await readFile(scriptPath, \"utf-8\");\n } catch {\n return false;\n }\n if (!hasEnvVarHookPattern(content)) return false;\n await rewriter();\n return true;\n}\n\n/**\n * Detect and rewrite the hook stdin-input bug:\n * 1. Inline hook commands in settings.json that read $TOOL_INPUT_* env vars\n * 2. Wrapper scripts (workflow-check.sh, sprint-open-check.sh) that do the same\n *\n * Known shapes (the hooks we generate) are rewritten to the canonical jq+stdin\n * form. User-customized hooks with the same env-var pattern are left alone —\n * the analyzer's HIGH finding still surfaces them so the user can fix manually.\n */\nexport async function rewriteEnvVarHooks(root: string): Promise<boolean> {\n let didFix = false;\n\n // 1. Inline commands in settings.json\n const settings = await readSettingsJson(root);\n if (settings !== null) {\n const outcome = rewriteSettingsHooks(settings as Record<string, unknown>);\n if (outcome.changed) {\n await writeSettingsJson(root, outcome.settings);\n log.success(\"Rewrote inert $TOOL_INPUT_* hooks in settings.json to canonical jq+stdin form\");\n didFix = true;\n }\n }\n\n // 2. workflow-check.sh wrapper script\n const workflowCheckPath = join(root, \".claude\", \"hooks\", \"workflow-check.sh\");\n if (await rewriteWrapperScript(workflowCheckPath, () => writeWorkflowCheckScript(root))) {\n log.success(\"Rewrote .claude/hooks/workflow-check.sh to canonical jq+stdin form\");\n didFix = true;\n }\n\n // 3. sprint-open-check.sh wrapper script (writeSprintHygieneScripts re-writes both\n // sprint-size and sprint-open; sprint-size has no bug so re-writing is harmless)\n const sprintOpenPath = join(root, \".claude\", \"hooks\", \"sprint-open-check.sh\");\n if (await rewriteWrapperScript(sprintOpenPath, () => writeSprintHygieneScripts(root))) {\n log.success(\"Rewrote .claude/hooks/sprint-open-check.sh to canonical jq+stdin form\");\n didFix = true;\n }\n\n return didFix;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { log } from \"../../lib/output.js\";\nimport { readSettingsJson, writeSettingsJson, readSettingsLocalJson, writeSettingsLocalJson } from \"../../lib/settings.js\";\nimport { addOrUpdateHook, type HookEntry } from \"../../lib/hook-builder.js\";\nimport type { MemoryPlacement } from \"../../types/index.js\";\n\n// ─── Shared Hook Helper (placement-aware) ───\n\nasync function addPlacementHook(\n root: string,\n placement: MemoryPlacement,\n event: string,\n dedupKeyword: string,\n entry: Record<string, unknown>,\n prepend: boolean,\n successMsg: string,\n): Promise<boolean> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) return false;\n const existingHooks = settings.hooks as Record<string, unknown[]> | undefined;\n\n const result = addOrUpdateHook(existingHooks, {\n event,\n dedupKeyword,\n entry: entry as unknown as HookEntry,\n prepend,\n });\n if (!result.added) return false;\n\n await write(root, { ...settings, hooks: result.hooks });\n log.success(successMsg);\n return true;\n}\n\n// ─── Memory Fix Functions ───\n\nexport async function disableAutoMemory(root: string, placement: MemoryPlacement): Promise<boolean> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) return false;\n if (settings.autoMemoryEnabled === false) return false;\n\n const updated = { ...settings, autoMemoryEnabled: false };\n await write(root, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Set autoMemoryEnabled: false in ${target}`);\n return true;\n}\n\nexport async function addMemoryToolPermissions(root: string, placement: MemoryPlacement): Promise<boolean> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) return false;\n const permissions = (settings.permissions ?? {}) as Record<string, unknown>;\n const allow = (permissions.allow as string[] | undefined) ?? [];\n\n const tools = [\n \"mcp__agentic-memory__memory_store\",\n \"mcp__agentic-memory__memory_search\",\n \"mcp__agentic-memory__memory_recent\",\n \"mcp__agentic-memory__memory_forget\",\n \"mcp__agentic-memory__memory_relate\",\n \"mcp__agentic-memory__memory_stats\",\n \"mcp__agentic-memory__memory_update\",\n ];\n\n const missing = tools.filter((t) => !allow.includes(t));\n if (missing.length === 0) return false;\n\n const updated = { ...settings, permissions: { ...permissions, allow: [...allow, ...missing] } };\n await write(root, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Added agentic-memory MCP tool permissions to ${target}`);\n return true;\n}\n\nexport async function addSessionStartPullHook(root: string, placement: MemoryPlacement): Promise<boolean> {\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n return addPlacementHook(root, placement, \"SessionStart\", \"memory pull\", {\n matcher: \"startup\",\n hooks: [{ type: \"command\", command: \"npx claude-launchpad memory pull -y 2>/dev/null; exit 0\" }],\n }, true, `Added SessionStart hook for memory sync to ${target}`);\n}\n\nexport async function addSessionEndPushHook(root: string, placement: MemoryPlacement): Promise<boolean> {\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n return addPlacementHook(root, placement, \"SessionEnd\", \"memory push\", {\n hooks: [{ type: \"command\", command: \"nohup npx claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0\" }],\n }, false, `Added SessionEnd hook for memory sync to ${target}`);\n}\n\nexport async function upgradeStaleSessionEndPushHook(root: string): Promise<boolean> {\n let changedAny = false;\n for (const placement of [\"shared\", \"local\"] as const) {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) continue;\n const hooks = settings.hooks as Record<string, unknown[]> | undefined;\n const sessionEnd = hooks?.SessionEnd as Record<string, unknown>[] | undefined;\n if (!sessionEnd) continue;\n\n let changed = false;\n const upgraded = sessionEnd.map((group) => {\n const inner = group.hooks as Record<string, unknown>[] | undefined;\n if (!inner) return group;\n const rewritten = inner.map((h) => {\n const cmd = typeof h.command === \"string\" ? h.command : \"\";\n if (!cmd.includes(\"memory push\") || cmd.includes(\"nohup\")) return h;\n changed = true;\n return { ...h, command: \"nohup npx claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0\" };\n });\n return { ...group, hooks: rewritten };\n });\n if (!changed) continue;\n\n const updated = { ...settings, hooks: { ...hooks, SessionEnd: upgraded } };\n await write(root, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Upgraded SessionEnd push hook in ${target} (now nohup-wrapped)`);\n changedAny = true;\n }\n return changedAny;\n}\n\nexport async function removeStaleStopHook(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n if (settings === null) return false;\n const hooks = settings.hooks as Record<string, unknown[]> | undefined;\n if (!hooks?.Stop) return false;\n\n const stopHooks = hooks.Stop as Record<string, unknown>[];\n const filtered = stopHooks.filter((h) => {\n const innerHooks = h.hooks as Record<string, unknown>[] | undefined;\n return !innerHooks?.some(\n (ih) => typeof ih.command === \"string\" && (ih.command as string).includes(\"memory extract\"),\n );\n });\n\n if (filtered.length === stopHooks.length) return false;\n\n const updated = filtered.length === 0\n ? (({ Stop: _, ...rest }) => rest)(hooks as Record<string, unknown>)\n : { ...hooks, Stop: filtered };\n const updatedSettings = { ...settings, hooks: updated };\n await writeSettingsJson(root, updatedSettings);\n log.success(\"Removed deprecated Stop hook (memory extract)\");\n return true;\n}\n\n// ─── MCP Fix Functions ───\n\n/**\n * Prepend agentic-memory to allowedMcpServers when the allowlist is present but excludes it.\n * Only touches whichever placement already holds the allowlist — does not create one.\n */\nexport async function addMemoryToAllowedMcpServers(root: string): Promise<boolean> {\n let changed = false;\n for (const placement of [\"shared\", \"local\"] as const) {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) continue;\n const existing = settings.allowedMcpServers as unknown;\n if (!Array.isArray(existing)) continue;\n\n const list = existing as Array<{ serverName?: unknown }>;\n const hasMemory = list.some((e) => e && typeof e === \"object\" && e.serverName === \"agentic-memory\");\n if (hasMemory) continue;\n\n const updated = {\n ...settings,\n allowedMcpServers: [{ serverName: \"agentic-memory\" }, ...list],\n };\n await write(root, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Added agentic-memory to allowedMcpServers in ${target}`);\n changed = true;\n }\n return changed;\n}\n\nexport async function addAllowedMcpServers(root: string, placement: MemoryPlacement): Promise<boolean> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) return false;\n if (settings.allowedMcpServers) return false;\n const other = placement === \"local\" ? await readSettingsJson(root) : await readSettingsLocalJson(root);\n if (other === null) return false;\n if (other.allowedMcpServers) return false;\n\n const serverNames = new Set<string>();\n const settingsServers = settings.mcpServers as Record<string, unknown> | undefined;\n if (settingsServers && typeof settingsServers === \"object\") {\n for (const name of Object.keys(settingsServers)) serverNames.add(name);\n }\n const mcpJsonPath = join(root, \".mcp.json\");\n try {\n const mcpJson = JSON.parse(await readFile(mcpJsonPath, \"utf-8\")) as Record<string, unknown>;\n const mcpServers = mcpJson.mcpServers as Record<string, unknown> | undefined;\n if (mcpServers && typeof mcpServers === \"object\") {\n for (const name of Object.keys(mcpServers)) serverNames.add(name);\n }\n } catch { /* no .mcp.json */ }\n\n if (serverNames.size === 0) return false;\n\n const updatedSettings = {\n ...settings,\n allowedMcpServers: [...serverNames].map((name) => ({ serverName: name })),\n };\n await write(root, updatedSettings);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Added allowedMcpServers from configured servers to ${target}`);\n return true;\n}\n\n/** Rewrite bare `claude-launchpad memory ...` hook commands to the npx form (both settings files, all events). */\nexport async function upgradeBareMemoryHooks(root: string): Promise<boolean> {\n let any = false;\n for (const placement of [\"shared\", \"local\"] as const) {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(root);\n if (settings === null) continue;\n const hooks = settings.hooks as Record<string, unknown[]> | undefined;\n if (!hooks) continue;\n\n let changed = false;\n const upgradedHooks: Record<string, unknown[]> = {};\n for (const [event, groups] of Object.entries(hooks)) {\n upgradedHooks[event] = (groups as Record<string, unknown>[]).map((group) => {\n const inner = group.hooks as Record<string, unknown>[] | undefined;\n if (!inner) return group;\n const rewritten = inner.map((h) => {\n const cmd = typeof h.command === \"string\" ? h.command : \"\";\n if (!cmd.includes(\"claude-launchpad memory\") || cmd.includes(\"npx claude-launchpad\")) return h;\n changed = true;\n return { ...h, command: cmd.replace(\"claude-launchpad memory\", \"npx claude-launchpad memory\") };\n });\n return { ...group, hooks: rewritten };\n });\n }\n if (!changed) continue;\n\n await write(root, { ...settings, hooks: upgradedHooks });\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Rewrote bare memory hook commands to npx form in ${target}`);\n any = true;\n }\n return any;\n}\n"],"mappings":"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,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,4BAA4B,qBAAqB;AAAA,IACjD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,wBAAwB,MAAM,IAAI;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,I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","names":["readFile","writeFile","mkdir","join","readFile","writeFile","mkdir","join","writeFile","readFile","join","updated","join","join","writeFile","join","readFile","readFile","writeFile","mkdir","join","join","mkdir","writeFile","readFile","readFile","join","readFile","join","readFile","join","join","readFile","join","readFile","writeFile","mkdir","readFile","join","mkdir","writeFile"]}