claude-launchpad 1.3.0 → 1.4.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 (44) hide show
  1. package/README.md +2 -2
  2. package/dist/{chunk-UJP5PJTA.js → chunk-ADZ45KHX.js} +3 -3
  3. package/dist/{chunk-V4NXT4KB.js → chunk-DXDOVWOA.js} +64 -8
  4. package/dist/chunk-DXDOVWOA.js.map +1 -0
  5. package/dist/{chunk-N6X3E5AX.js → chunk-F6SLV2FR.js} +24 -5
  6. package/dist/chunk-F6SLV2FR.js.map +1 -0
  7. package/dist/{chunk-AR64LWGW.js → chunk-RJEPJ4JE.js} +25 -4
  8. package/dist/chunk-RJEPJ4JE.js.map +1 -0
  9. package/dist/{chunk-YXPJDIMK.js → chunk-UQOBOHKN.js} +33 -2
  10. package/dist/chunk-UQOBOHKN.js.map +1 -0
  11. package/dist/{chunk-J765H3HZ.js → chunk-WOC2PKT2.js} +2 -2
  12. package/dist/{chunk-F5PNKQKW.js → chunk-YZ53W47Z.js} +7 -2
  13. package/dist/chunk-YZ53W47Z.js.map +1 -0
  14. package/dist/cli.js +24 -13
  15. package/dist/cli.js.map +1 -1
  16. package/dist/commands/memory/server.js +5 -5
  17. package/dist/{context-VAXF3EW3.js → context-NCV46PTY.js} +6 -6
  18. package/dist/{install-M3JWBGMK.js → install-DORMJYCU.js} +6 -6
  19. package/dist/install-DORMJYCU.js.map +1 -0
  20. package/dist/{pull-ZQFCMK46.js → pull-UYLUGILU.js} +9 -9
  21. package/dist/{push-5ZJNWAE7.js → push-HWXJGSTL.js} +40 -17
  22. package/dist/push-HWXJGSTL.js.map +1 -0
  23. package/dist/{require-deps-QW2IU6I3.js → require-deps-RUXTMQUV.js} +3 -3
  24. package/dist/{stats-NPXPJNBO.js → stats-DFV24AJW.js} +7 -7
  25. package/dist/{sync-clean-JQLVE4WU.js → sync-clean-GFX5F55E.js} +2 -2
  26. package/dist/{sync-status-IYG7ZYC5.js → sync-status-VXMDWDRG.js} +9 -9
  27. package/dist/{tui-74FMIMUM.js → tui-ELOJ37ZA.js} +5 -5
  28. package/package.json +1 -1
  29. package/dist/chunk-AR64LWGW.js.map +0 -1
  30. package/dist/chunk-F5PNKQKW.js.map +0 -1
  31. package/dist/chunk-N6X3E5AX.js.map +0 -1
  32. package/dist/chunk-V4NXT4KB.js.map +0 -1
  33. package/dist/chunk-YXPJDIMK.js.map +0 -1
  34. package/dist/install-M3JWBGMK.js.map +0 -1
  35. package/dist/push-5ZJNWAE7.js.map +0 -1
  36. /package/dist/{chunk-UJP5PJTA.js.map → chunk-ADZ45KHX.js.map} +0 -0
  37. /package/dist/{chunk-J765H3HZ.js.map → chunk-WOC2PKT2.js.map} +0 -0
  38. /package/dist/{context-VAXF3EW3.js.map → context-NCV46PTY.js.map} +0 -0
  39. /package/dist/{pull-ZQFCMK46.js.map → pull-UYLUGILU.js.map} +0 -0
  40. /package/dist/{require-deps-QW2IU6I3.js.map → require-deps-RUXTMQUV.js.map} +0 -0
  41. /package/dist/{stats-NPXPJNBO.js.map → stats-DFV24AJW.js.map} +0 -0
  42. /package/dist/{sync-clean-JQLVE4WU.js.map → sync-clean-GFX5F55E.js.map} +0 -0
  43. /package/dist/{sync-status-IYG7ZYC5.js.map → sync-status-VXMDWDRG.js.map} +0 -0
  44. /package/dist/{tui-74FMIMUM.js.map → tui-ELOJ37ZA.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/memory/storage/memory-repo.ts","../src/commands/memory/storage/relation-repo.ts","../src/commands/memory/storage/search-repo.ts"],"sourcesContent":["import type Database from 'better-sqlite3';\nimport type { Memory, MemoryType, MemorySource, StoreInput, SyncMemoryRow } from '../types.js';\nimport { randomUUID, createHash } from 'node:crypto';\n\nfunction safeParseTags(raw: string): string[] {\n try {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed.filter(t => typeof t === 'string') : [];\n } catch {\n return [];\n }\n}\n\n// ── Row shape from SQLite ─────────────────────────────────────\n\ninterface MemoryRow {\n id: string;\n type: string;\n title: string | null;\n content: string;\n context: string | null;\n source: string | null;\n project: string | null;\n tags: string;\n importance: number;\n created_at: string;\n updated_at: string;\n access_count: number;\n last_accessed: string | null;\n injection_count: number;\n embedding: Buffer | null;\n}\n\nfunction rowToMemory(row: MemoryRow): Memory {\n return {\n id: row.id,\n type: row.type as MemoryType,\n title: row.title,\n content: row.content,\n context: row.context,\n source: row.source as MemorySource | null,\n project: row.project,\n tags: safeParseTags(row.tags),\n importance: row.importance,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n accessCount: row.access_count,\n lastAccessed: row.last_accessed,\n injectionCount: row.injection_count,\n };\n}\n\n// ── Repository ────────────────────────────────────────────────\n\nexport class MemoryRepo {\n readonly #stmts;\n readonly db: Database.Database;\n\n constructor(db: Database.Database) {\n this.db = db;\n this.#stmts = {\n insert: db.prepare(`\n INSERT OR IGNORE INTO memories (id, type, title, content, context, source, project, tags, importance, created_at, updated_at, embedding, content_hash)\n VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance, @createdAt, @updatedAt, @embedding, @contentHash)\n `),\n getById: db.prepare('SELECT * FROM memories WHERE id = ?'),\n getAll: db.prepare('SELECT * FROM memories ORDER BY created_at DESC'),\n getAllByProject: db.prepare('SELECT * FROM memories WHERE project = ? OR project IS NULL ORDER BY created_at DESC'),\n getByType: db.prepare('SELECT * FROM memories WHERE type = ? ORDER BY created_at DESC'),\n getByTypeAndProject: db.prepare('SELECT * FROM memories WHERE type = ? AND (project = ? OR project IS NULL) ORDER BY created_at DESC'),\n getRecent: db.prepare('SELECT * FROM memories ORDER BY created_at DESC LIMIT ?'),\n getRecentByProject: db.prepare('SELECT * FROM memories WHERE project = ? OR project IS NULL ORDER BY created_at DESC LIMIT ?'),\n getRecentByTypeAndProject: db.prepare('SELECT * FROM memories WHERE type = ? AND (project = ? OR project IS NULL) ORDER BY created_at DESC LIMIT ?'),\n update: db.prepare(`\n UPDATE memories\n SET title = @title, content = @content, context = @context, tags = @tags,\n importance = @importance, updated_at = @updatedAt, embedding = @embedding,\n content_hash = @contentHash\n WHERE id = @id\n `),\n updateImportance: db.prepare('UPDATE memories SET importance = ?, updated_at = ? WHERE id = ?'),\n updateImportanceOnly: db.prepare('UPDATE memories SET importance = ? WHERE id = ?'),\n incrementAccess: db.prepare(`\n UPDATE memories SET access_count = access_count + 1, last_accessed = ? WHERE id = ?\n `),\n incrementInjection: db.prepare(`\n UPDATE memories SET injection_count = injection_count + 1 WHERE id = ?\n `),\n softDelete: db.prepare('UPDATE memories SET importance = 0, updated_at = ? WHERE id = ?'),\n hardDelete: db.prepare('DELETE FROM memories WHERE id = ?'),\n deleteByType: db.prepare('DELETE FROM memories WHERE type = ?'),\n deleteByProject: db.prepare('DELETE FROM memories WHERE project = ?'),\n count: db.prepare('SELECT COUNT(*) as count FROM memories'),\n countByProject: db.prepare('SELECT COUNT(*) as count FROM memories WHERE project = ?'),\n countByType: db.prepare('SELECT type, COUNT(*) as count FROM memories GROUP BY type'),\n projectCounts: db.prepare('SELECT COALESCE(project, \\'_global\\') as project, COUNT(*) as count FROM memories GROUP BY project'),\n dateRange: db.prepare('SELECT MIN(created_at) as oldest, MAX(created_at) as newest FROM memories'),\n topInjected: db.prepare(`\n SELECT id, title, injection_count FROM memories\n WHERE injection_count > 0 ORDER BY injection_count DESC LIMIT ?\n `),\n insertSync: db.prepare(`\n INSERT OR IGNORE INTO memories\n (id, type, title, content, context, source, project, tags, importance,\n access_count, injection_count, created_at, updated_at, last_accessed, embedding, content_hash)\n VALUES (@id, @type, @title, @content, @context, @source, @project, @tags, @importance,\n @accessCount, @injectionCount, @createdAt, @updatedAt, @lastAccessed, NULL, @contentHash)\n `),\n updateSync: db.prepare(`\n UPDATE memories SET\n title = @title, content = @content, context = @context,\n source = @source, project = @project, tags = @tags,\n importance = @importance, access_count = @accessCount,\n injection_count = @injectionCount, updated_at = @updatedAt,\n last_accessed = @lastAccessed, content_hash = @contentHash\n WHERE id = @id\n `),\n getAllStrictProject: db.prepare(\n 'SELECT * FROM memories WHERE project = ? ORDER BY created_at DESC'\n ),\n };\n }\n\n create(input: StoreInput, _embedding: Buffer | null = null): Memory | null {\n const now = new Date().toISOString();\n const id = randomUUID();\n const contentHash = createHash('sha256').update(input.content).digest('hex');\n\n const params = {\n id,\n type: input.type,\n title: input.title ?? null,\n content: input.content,\n context: input.context ?? null,\n source: input.source,\n project: input.project ?? null,\n tags: JSON.stringify(input.tags),\n importance: input.importance,\n createdAt: now,\n updatedAt: now,\n embedding: null,\n contentHash,\n };\n\n const result = this.#stmts.insert.run(params);\n if (result.changes === 0) return null;\n\n const row: MemoryRow = {\n id,\n type: input.type,\n title: input.title ?? null,\n content: input.content,\n context: input.context ?? null,\n source: input.source,\n project: input.project ?? null,\n tags: JSON.stringify(input.tags),\n importance: input.importance,\n created_at: now,\n updated_at: now,\n access_count: 0,\n last_accessed: null,\n injection_count: 0,\n embedding: null,\n };\n\n return rowToMemory(row);\n }\n\n getById(id: string): Memory | undefined {\n const row = this.#stmts.getById.get(id) as MemoryRow | undefined;\n return row ? rowToMemory(row) : undefined;\n }\n\n getAll(project?: string): readonly Memory[] {\n if (project) {\n const rows = this.#stmts.getAllByProject.all(project) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n const rows = this.#stmts.getAll.all() as MemoryRow[];\n return rows.map(rowToMemory);\n }\n\n getRecent(limit: number, project?: string, type?: MemoryType): readonly Memory[] {\n if (type && project) {\n const rows = this.#stmts.getRecentByTypeAndProject.all(type, project, limit) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n if (project) {\n const rows = this.#stmts.getRecentByProject.all(project, limit) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n const rows = this.#stmts.getRecent.all(limit) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n\n getByType(type: MemoryType, project?: string): readonly Memory[] {\n if (project) {\n const rows = this.#stmts.getByTypeAndProject.all(type, project) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n const rows = this.#stmts.getByType.all(type) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n\n updateContent(id: string, updates: {\n readonly title?: string | null;\n readonly content?: string;\n readonly context?: string | null;\n readonly tags?: readonly string[];\n readonly importance?: number;\n }): boolean {\n const existing = this.getById(id);\n if (!existing) return false;\n\n const now = new Date().toISOString();\n\n const finalContent = updates.content ?? existing.content;\n const params = {\n id,\n title: updates.title !== undefined ? updates.title : existing.title,\n content: finalContent,\n context: updates.context !== undefined ? updates.context : existing.context,\n tags: JSON.stringify(updates.tags ?? existing.tags),\n importance: updates.importance ?? existing.importance,\n updatedAt: now,\n embedding: null,\n contentHash: createHash('sha256').update(finalContent).digest('hex'),\n };\n\n this.#stmts.update.run(params);\n return true;\n }\n\n updateImportance(id: string, importance: number): boolean {\n const now = new Date().toISOString();\n const result = this.#stmts.updateImportance.run(importance, now, id);\n return result.changes > 0;\n }\n\n /** Update importance without touching updated_at - used by decay to avoid resetting the clock. */\n updateImportanceOnly(id: string, importance: number): boolean {\n const result = this.#stmts.updateImportanceOnly.run(importance, id);\n return result.changes > 0;\n }\n\n incrementAccess(id: string): void {\n this.#stmts.incrementAccess.run(new Date().toISOString(), id);\n }\n\n incrementInjection(id: string): void {\n this.#stmts.incrementInjection.run(id);\n }\n\n softDelete(id: string): boolean {\n const result = this.#stmts.softDelete.run(new Date().toISOString(), id);\n return result.changes > 0;\n }\n\n hardDelete(id: string): boolean {\n const result = this.#stmts.hardDelete.run(id);\n return result.changes > 0;\n }\n\n deleteByType(type: MemoryType): number {\n const result = this.#stmts.deleteByType.run(type);\n return result.changes;\n }\n\n deleteByProject(project: string): number {\n const result = this.#stmts.deleteByProject.run(project);\n return result.changes;\n }\n\n count(project?: string): number {\n if (project) {\n const row = this.#stmts.countByProject.get(project) as { count: number };\n return row.count;\n }\n const row = this.#stmts.count.get() as { count: number };\n return row.count;\n }\n\n countByType(): Record<string, number> {\n const rows = this.#stmts.countByType.all() as { type: string; count: number }[];\n return Object.fromEntries(rows.map(r => [r.type, r.count]));\n }\n\n projectCounts(): ReadonlyMap<string, number> {\n const rows = this.#stmts.projectCounts.all() as { project: string; count: number }[];\n return new Map(rows.map(r => [r.project, r.count]));\n }\n\n dateRange(): { oldest: string | null; newest: string | null } {\n const row = this.#stmts.dateRange.get() as { oldest: string | null; newest: string | null };\n return { oldest: row.oldest, newest: row.newest };\n }\n\n topInjected(limit: number = 5): readonly { id: string; title: string | null; injectionCount: number }[] {\n const rows = this.#stmts.topInjected.all(limit) as { id: string; title: string | null; injection_count: number }[];\n return rows.map(r => ({ id: r.id, title: r.title, injectionCount: r.injection_count }));\n }\n\n upsertFromSync(row: SyncMemoryRow): void {\n const params = {\n id: row.id,\n type: row.type,\n title: row.title,\n content: row.content,\n context: row.context,\n source: row.source,\n project: row.project,\n tags: JSON.stringify(row.tags),\n importance: row.importance,\n accessCount: row.access_count,\n injectionCount: row.injection_count,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n lastAccessed: row.last_accessed,\n contentHash: createHash('sha256').update(row.content).digest('hex'),\n };\n\n const existing = this.getById(row.id);\n if (existing) {\n this.#stmts.updateSync.run(params);\n } else {\n this.#stmts.insertSync.run(params);\n }\n }\n\n getAllForSync(project?: string): readonly Memory[] {\n if (project) {\n const rows = this.#stmts.getAllStrictProject.all(project) as MemoryRow[];\n return rows.map(rowToMemory);\n }\n return this.getAll();\n }\n}\n","import type Database from 'better-sqlite3';\nimport type { Relation, RelationType } from '../types.js';\n\ninterface RelationRow {\n source_id: string;\n target_id: string;\n relation_type: string;\n created_at: string;\n}\n\nfunction rowToRelation(row: RelationRow): Relation {\n return {\n sourceId: row.source_id,\n targetId: row.target_id,\n relationType: row.relation_type as RelationType,\n createdAt: row.created_at,\n };\n}\n\nexport class RelationRepo {\n readonly #stmts;\n\n constructor(db: Database.Database) {\n this.#stmts = {\n insert: db.prepare(`\n INSERT OR IGNORE INTO relations (source_id, target_id, relation_type)\n VALUES (?, ?, ?)\n `),\n getBySource: db.prepare('SELECT * FROM relations WHERE source_id = ?'),\n getByTarget: db.prepare('SELECT * FROM relations WHERE target_id = ?'),\n getByMemory: db.prepare(`\n SELECT * FROM relations WHERE source_id = ? OR target_id = ?\n `),\n delete: db.prepare(`\n DELETE FROM relations WHERE source_id = ? AND target_id = ? AND relation_type = ?\n `),\n countByMemory: db.prepare(`\n SELECT COUNT(*) as count FROM relations WHERE source_id = ? OR target_id = ?\n `),\n count: db.prepare('SELECT COUNT(*) as count FROM relations'),\n getAll: db.prepare('SELECT * FROM relations'),\n deleteOrphaned: db.prepare(`\n DELETE FROM relations\n WHERE source_id NOT IN (SELECT id FROM memories)\n OR target_id NOT IN (SELECT id FROM memories)\n `),\n };\n }\n\n create(sourceId: string, targetId: string, relationType: RelationType): boolean {\n const result = this.#stmts.insert.run(sourceId, targetId, relationType);\n return result.changes > 0;\n }\n\n getBySource(sourceId: string): readonly Relation[] {\n const rows = this.#stmts.getBySource.all(sourceId) as RelationRow[];\n return rows.map(rowToRelation);\n }\n\n getByTarget(targetId: string): readonly Relation[] {\n const rows = this.#stmts.getByTarget.all(targetId) as RelationRow[];\n return rows.map(rowToRelation);\n }\n\n getByMemory(memoryId: string): readonly Relation[] {\n const rows = this.#stmts.getByMemory.all(memoryId, memoryId) as RelationRow[];\n return rows.map(rowToRelation);\n }\n\n delete(sourceId: string, targetId: string, relationType: RelationType): boolean {\n const result = this.#stmts.delete.run(sourceId, targetId, relationType);\n return result.changes > 0;\n }\n\n countByMemory(memoryId: string): number {\n const row = this.#stmts.countByMemory.get(memoryId, memoryId) as { count: number };\n return row.count;\n }\n\n count(): number {\n const row = this.#stmts.count.get() as { count: number };\n return row.count;\n }\n\n getAll(): readonly Relation[] {\n const rows = this.#stmts.getAll.all() as RelationRow[];\n return rows.map(rowToRelation);\n }\n\n deleteOrphaned(): number {\n const result = this.#stmts.deleteOrphaned.run();\n return result.changes;\n }\n}\n","import type Database from 'better-sqlite3';\nimport type { FtsMatch, MemoryType } from '../types.js';\n\n// ── FTS5 Search ───────────────────────────────────────────────\n\nexport interface FtsSearchOptions {\n readonly query: string;\n readonly limit: number;\n readonly type?: MemoryType;\n readonly minImportance?: number;\n readonly project?: string;\n}\n\n\nexport class SearchRepo {\n readonly #stmts;\n\n constructor(db: Database.Database) {\n // FTS5 search with BM25 ranking (weights: title=5.0, content=1.0, tags=2.0)\n this.#stmts = {\n ftsSearch: db.prepare(`\n SELECT\n m.rowid,\n m.id as memory_id,\n bm25(memories_fts, 5.0, 1.0, 2.0) as rank\n FROM memories_fts f\n JOIN memories m ON m.rowid = f.rowid\n WHERE memories_fts MATCH @query\n ORDER BY rank\n LIMIT @limit\n `),\n ftsSearchByProject: db.prepare(`\n SELECT\n m.rowid,\n m.id as memory_id,\n bm25(memories_fts, 5.0, 1.0, 2.0) as rank\n FROM memories_fts f\n JOIN memories m ON m.rowid = f.rowid\n WHERE memories_fts MATCH @query\n AND (m.project = @project OR m.project IS NULL)\n ORDER BY rank\n LIMIT @limit\n `),\n ftsSearchFiltered: db.prepare(`\n SELECT\n m.rowid,\n m.id as memory_id,\n bm25(memories_fts, 5.0, 1.0, 2.0) as rank\n FROM memories_fts f\n JOIN memories m ON m.rowid = f.rowid\n WHERE memories_fts MATCH @query\n AND m.type = @type\n AND m.importance >= @minImportance\n ORDER BY rank\n LIMIT @limit\n `),\n ftsSearchFilteredByProject: db.prepare(`\n SELECT\n m.rowid,\n m.id as memory_id,\n bm25(memories_fts, 5.0, 1.0, 2.0) as rank\n FROM memories_fts f\n JOIN memories m ON m.rowid = f.rowid\n WHERE memories_fts MATCH @query\n AND m.type = @type\n AND m.importance >= @minImportance\n AND (m.project = @project OR m.project IS NULL)\n ORDER BY rank\n LIMIT @limit\n `),\n };\n }\n\n /**\n * Full-text search using BM25 ranking.\n * Returns matches sorted by relevance (most relevant first).\n */\n searchFts(options: FtsSearchOptions): readonly FtsMatch[] {\n const ftsQuery = toFtsQuery(options.query);\n if (!ftsQuery) return [];\n\n try {\n const hasType = !!options.type;\n const hasProject = !!options.project;\n\n let rows: FtsRow[];\n if (hasType && hasProject) {\n rows = this.#stmts.ftsSearchFilteredByProject.all({\n query: ftsQuery, limit: options.limit,\n type: options.type, minImportance: options.minImportance ?? 0,\n project: options.project,\n }) as FtsRow[];\n } else if (hasType) {\n rows = this.#stmts.ftsSearchFiltered.all({\n query: ftsQuery, limit: options.limit,\n type: options.type, minImportance: options.minImportance ?? 0,\n }) as FtsRow[];\n } else if (hasProject) {\n rows = this.#stmts.ftsSearchByProject.all({\n query: ftsQuery, limit: options.limit,\n project: options.project,\n }) as FtsRow[];\n } else {\n rows = this.#stmts.ftsSearch.all({\n query: ftsQuery, limit: options.limit,\n }) as FtsRow[];\n }\n\n return rows.map(r => ({\n rowid: r.rowid,\n memoryId: r.memory_id,\n rank: r.rank,\n }));\n } catch (err) {\n // FTS5 MATCH throws on invalid query syntax - degrade gracefully\n console.error('[agentic-memory] FTS5 search error:', err instanceof Error ? err.message : err);\n return [];\n }\n }\n\n}\n\n// ── Internal helpers ──────────────────────────────────────────\n\ninterface FtsRow {\n rowid: number;\n memory_id: string;\n rank: number;\n}\n\n// Synonym expansion for common dev terms\nconst SYNONYMS: Record<string, readonly string[]> = {\n auth: ['authentication', 'login', 'oauth', 'jwt'],\n authentication: ['auth', 'login', 'oauth'],\n login: ['auth', 'authentication', 'signin'],\n db: ['database', 'sql', 'sqlite', 'postgres'],\n database: ['db', 'sql', 'sqlite', 'postgres'],\n api: ['endpoint', 'route', 'rest', 'graphql'],\n deploy: ['deployment', 'release', 'ship', 'publish'],\n test: ['testing', 'spec', 'jest', 'vitest'],\n config: ['configuration', 'settings', 'setup'],\n err: ['error', 'exception', 'crash', 'bug'],\n error: ['err', 'exception', 'crash', 'bug'],\n};\n\n/**\n * Convert a natural language query to FTS5 query syntax.\n * Expands synonyms and wraps words in quotes for safe matching.\n */\nfunction toFtsQuery(input: string): string | null {\n const words = input\n .replace(/[^\\w\\s]/g, ' ')\n .split(/\\s+/)\n .filter(w => w.length > 0);\n\n if (words.length === 0) return null;\n\n const expanded = words.flatMap((w) => {\n const lower = w.toLowerCase();\n const syns = SYNONYMS[lower];\n return syns ? [w, ...syns] : [w];\n });\n\n return [...new Set(expanded)].map(w => `\"${w}\"`).join(' OR ');\n}\n"],"mappings":"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","names":["rows","row"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/fs-utils.ts","../src/lib/settings.ts","../src/lib/memory-placement.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/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\";\n\nexport async function readSettingsJson(root: string): Promise<Record<string, unknown>> {\n const path = join(root, \".claude\", \"settings.json\");\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return {};\n }\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>> {\n const path = join(root, \".claude\", \"settings.local.json\");\n try {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return {};\n }\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 { 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","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\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 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, access } 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, BACKLOG_CONTENT, STOP_AND_SWARM_CONTENT,\n OFF_LIMITS_CONTENT, 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 { readSettingsJson, writeSettingsJson } from \"../../lib/settings.js\";\nimport { getMemoryPlacement } from \"../../lib/memory-placement.js\";\nimport {\n disableAutoMemory, addMemoryToolPermissions, addAllowedMcpServers,\n addSessionStartPullHook, addSessionEndPushHook, removeStaleStopHook,\n} from \"./fixer-memory.js\";\nimport type { DiagnosticIssue, DetectedProject, MemoryPlacement } 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 ? await getMemoryPlacement(projectRoot) : \"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 = (root: string, detected: DetectedProject, placement: MemoryPlacement) => Promise<boolean>;\n\nconst FIX_TABLE: ReadonlyArray<{ analyzer: string; match: string; fix: FixFn }> = [\n { analyzer: \"Hooks\", match: \"No hooks configured\", 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 { analyzer: \"Hooks\", match: \".env file protection\", fix: (root) => addEnvProtectionHook(root) },\n { analyzer: \"Hooks\", match: \"auto-format\", fix: (root, detected) => addAutoFormatHook(root, detected) },\n { analyzer: \"Hooks\", match: \"No PreToolUse\", fix: (root) => addEnvProtectionHook(root) },\n { analyzer: \"Quality\", match: \"Architecture\", fix: (root) => addClaudeMdSection(root, \"## Architecture\", \"<!-- TODO: Describe your codebase structure. Run `/lp-enhance` to auto-fill this. -->\") },\n { analyzer: \"Quality\", match: \"Off-Limits\", fix: (root) => addClaudeMdSection(root, \"## Off-Limits\", OFF_LIMITS_CONTENT) },\n { analyzer: \"Quality\", match: \"Commands\", fix: (root) => addClaudeMdSection(root, \"## Commands\", \"<!-- TODO: Add your dev/build/test commands -->\") },\n { analyzer: \"Quality\", match: \"Stack\", fix: (root, detected) => {\n const content = detected.language\n ? `- **Language**: ${detected.language}${detected.framework ? `\\n- **Framework**: ${detected.framework}` : \"\"}${detected.packageManager ? `\\n- **Package Manager**: ${detected.packageManager}` : \"\"}`\n : \"<!-- TODO: Define your tech stack -->\";\n return addClaudeMdSection(root, \"## Stack\", content);\n }},\n { analyzer: \"Quality\", match: \"Session Start\", fix: (root) => addClaudeMdSection(root, \"## Session Start\", SESSION_START_CONTENT) },\n { analyzer: \"Quality\", match: \"Backlog\", fix: (root) => addClaudeMdSection(root, \"## Backlog\", BACKLOG_CONTENT) },\n { analyzer: \"Quality\", match: \"Stop-and-Swarm\", fix: (root) => addClaudeMdSection(root, \"## Stop-and-Swarm\", STOP_AND_SWARM_CONTENT) },\n { analyzer: \"Rules\", match: \"No BACKLOG.md\", fix: (root) => createBacklogMd(root) },\n { analyzer: \"Rules\", match: \"No .claudeignore\", fix: (root, detected) => createClaudeignore(root, detected) },\n { analyzer: \"Rules\", match: \"No .claude/rules/\", fix: (root) => createStarterRules(root) },\n { analyzer: \"Hooks\", match: \"PostCompact\", fix: (root) => addPostCompactHook(root) },\n { analyzer: \"Permissions\", match: \"force-push\", fix: (root) => addForcePushProtection(root) },\n { analyzer: \"Permissions\", match: \"Credential files not blocked\", fix: (root) => addCredentialDenyRules(root) },\n { analyzer: \"Permissions\", match: \"Bypass permissions mode\", fix: (root) => addBypassDisable(root) },\n { analyzer: \"Permissions\", match: \"Sandbox not enabled\", fix: (root) => addSandboxSettings(root) },\n { analyzer: \"Permissions\", match: \".env is protected by hooks but not in .claudeignore\", fix: (root) => addEnvToClaudeignore(root) },\n { analyzer: \"Rules\", match: \"No skill authoring conventions\", fix: (root) => addSkillAuthoringConventions(root) },\n { analyzer: \"Rules\", match: \"No /lp-enhance skill\", fix: (root) => createEnhanceSkill(root) },\n { analyzer: \"Rules\", match: \"lp-enhance skill is outdated\", fix: (root) => updateEnhanceSkill(root) },\n { analyzer: \"Settings\", match: \"Deprecated includeCoAuthoredBy\", fix: (root) => migrateAttribution(root) },\n { analyzer: \"Hooks\", match: \"SessionStart\", fix: (root) => addSessionStartHook(root) },\n { analyzer: \"Memory\", match: \"Deprecated Stop hook\", fix: (root) => removeStaleStopHook(root) },\n { analyzer: \"Memory\", match: \"autoMemoryEnabled not disabled\", fix: (root, _det, placement) => disableAutoMemory(root, placement) },\n { analyzer: \"Memory\", match: \"MCP tool permission\", fix: (root, _det, placement) => addMemoryToolPermissions(root, placement) },\n { analyzer: \"MCP\", match: \"no allowedMcpServers\", fix: (root, _det, placement) => addAllowedMcpServers(root, placement) },\n { analyzer: \"Memory\", match: \"SessionStart hook to auto-pull\", fix: (root, _det, placement) => addSessionStartPullHook(root, placement) },\n { analyzer: \"Memory\", match: \"SessionEnd hook to auto-push\", fix: (root, _det, placement) => addSessionEndPushHook(root, placement) },\n { analyzer: \"Memory\", match: \"CLAUDE.md missing memory guidance\", fix: (root, _det, placement) => {\n const content = \"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 = placement === \"local\" ? join(root, \".claude\", \"CLAUDE.md\") : undefined;\n return addClaudeMdSection(root, \"## Memory\", content, target);\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// ─── Hook Helper ───\n\nasync function addHook(\n root: string,\n event: string,\n dedupKeyword: string,\n entry: Record<string, unknown>,\n successMsg: string,\n): Promise<boolean> {\n const settings = await readSettingsJson(root);\n const hooks = (settings.hooks ?? {}) as Record<string, unknown>;\n const hookList = (hooks[event] as Record<string, unknown>[] | undefined) ?? [];\n\n const alreadyHas = hookList.some((g: Record<string, unknown>) => {\n const nested = g.hooks as Record<string, unknown>[] | undefined;\n return nested?.some((h) => String(h.command ?? \"\").includes(dedupKeyword));\n });\n if (alreadyHas) return false;\n\n const updated = [...hookList, entry];\n const updatedSettings = { ...settings, hooks: { ...hooks, [event]: updated } };\n await writeSettingsJson(root, updatedSettings);\n log.success(successMsg);\n return true;\n}\n\n// ─── Fix Implementations ───\n\nasync function addEnvProtectionHook(root: string): Promise<boolean> {\n return addHook(root, \"PreToolUse\", \".env\", {\n matcher: \"Read|Write|Edit\",\n hooks: [{\n type: \"command\",\n command: \"echo \\\"$TOOL_INPUT_FILE_PATH\\\" | grep -qE '\\\\.(env|env\\\\..*)$' && ! echo \\\"$TOOL_INPUT_FILE_PATH\\\" | grep -q '.env.example' && echo 'BLOCKED: .env files contain secrets' && exit 1; exit 0\",\n }],\n }, \"Added .env file protection hook (PreToolUse)\");\n}\n\nasync function addAutoFormatHook(root: string, detected: DetectedProject): Promise<boolean> {\n if (!detected.language) return false;\n\n const 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\n const config = formatters[detected.language];\n if (!config) return false;\n\n const extChecks = config.extensions.map((ext) => `[ \"$ext\" = \"${ext}\" ]`).join(\" || \");\n return addHook(root, \"PostToolUse\", \"format\", {\n matcher: \"Write|Edit\",\n hooks: [{\n type: \"command\",\n command: `ext=\\${TOOL_INPUT_FILE_PATH##*.}; (${extChecks}) && ${config.command} \"$TOOL_INPUT_FILE_PATH\" 2>/dev/null; exit 0`,\n }],\n }, `Added auto-format hook (PostToolUse → ${config.command})`);\n}\n\nasync function addForcePushProtection(root: string): Promise<boolean> {\n return addHook(root, \"PreToolUse\", \"force\", {\n matcher: \"Bash\",\n hooks: [{\n type: \"command\",\n command: \"echo \\\"$TOOL_INPUT_COMMAND\\\" | grep -qE 'push.*--force|push.*-f' && echo 'WARNING: Force push detected — this can destroy remote history' && exit 1; exit 0\",\n }],\n }, \"Added force-push protection hook (PreToolUse → Bash)\");\n}\n\nasync function addPostCompactHook(root: string): Promise<boolean> {\n return addHook(root, \"PostCompact\", \"TASKS.md\", {\n matcher: \"\",\n hooks: [{\n type: \"command\",\n command: \"cat TASKS.md 2>/dev/null; exit 0\",\n }],\n }, \"Added PostCompact hook (re-injects TASKS.md after compaction)\");\n}\n\nasync function addSessionStartHook(root: string): Promise<boolean> {\n return addHook(root, \"SessionStart\", \"TASKS.md\", {\n matcher: \"startup|resume\",\n hooks: [{\n type: \"command\",\n command: \"cat TASKS.md 2>/dev/null; exit 0\",\n }],\n }, \"Added SessionStart hook (injects TASKS.md at startup)\");\n}\n\nasync function migrateAttribution(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\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 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 = { ...settings, permissions: { ...permissions, deny: [...deny, ...missing] } };\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.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\nasync function addSandboxSettings(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\n const sandbox = settings.sandbox as Record<string, unknown> | undefined;\n if (sandbox?.enabled === true) return false;\n\n const updated = { ...settings, sandbox: { enabled: true, failIfUnavailable: true } };\n await writeSettingsJson(root, updated);\n log.success(\"Enabled sandbox with failIfUnavailable\");\n return true;\n}\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*\")) 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(root: string, heading: string, content: string, targetPath?: string): 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 = 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 try {\n await access(backlogPath);\n return false;\n } catch {\n // Create it\n }\n\n const name = root.split(\"/\").pop() ?? \"Project\";\n await writeFile(backlogPath, `# ${name} - Backlog\n\n> Features discussed but deferred. Pick up when relevant.\n> Priority: P0 = next sprint, P1 = soon, P2 = when relevant.\n`);\n log.success(\"Generated BACKLOG.md\");\n return true;\n}\n\nasync function createClaudeignore(root: string, detected: DetectedProject): Promise<boolean> {\n const ignorePath = join(root, \".claudeignore\");\n try {\n await access(ignorePath);\n return false; // Already exists\n } catch {\n // Create it\n }\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 try {\n await access(rulesDir);\n return false; // Already exists\n } catch {\n // Create it\n }\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(conventionsPath, content.trimEnd() + \"\\n\" + SKILL_AUTHORING_SECTION);\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(homedir(), \".claude\", \"skills\", \"lp-enhance\", \"SKILL.md\");\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 (await fileExists(skillPath) || await fileExists(globalPath)\n || await fileExists(legacyProject) || await fileExists(legacyGlobal)) 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(homedir(), \".claude\", \"skills\", \"lp-enhance\", \"SKILL.md\");\n\n const targetPath = await fileExists(projectPath) ? projectPath\n : await fileExists(globalPath) ? 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\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\nexport const STOP_AND_SWARM_CONTENT =\n \"Three failed iterations on the same problem = stop iterating alone.\\n\" +\n \"On the fourth attempt, spin up at least 3 parallel agents via the Agent tool, 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 \"Wait for all agents to return, synthesize their findings, then act.\\n\" +\n \"Don't keep guessing in circles — rotate perspectives.\";\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","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","/**\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 = 7;\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',\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** - ONLY if agentic-memory is configured in settings.json. Max 6 bullets.',\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 'When creating Claude Code skills (.claude/skills/*/SKILL.md):',\n '',\n '- Keep SKILL.md under 500 lines - move reference material to supporting files in the same directory',\n '- Front-load description (first 250 chars shown in listings) with TRIGGER when / DO NOT TRIGGER when clauses',\n '- Add allowed-tools in frontmatter to restrict tool access (e.g. Read, Glob, Grep for read-only skills)',\n '- Add argument-hint in frontmatter showing the expected input format (use $ARGUMENTS or $0, $1 for dynamic input)',\n '- Set disable-model-invocation: true for skills with side effects (deploy, send messages)',\n '- Structure as phases: Research, Plan, Execute, Verify with \"Done when:\" success criteria per phase',\n '- Handle edge cases and preconditions before execution',\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 no PostCompact hook exists, suggest one that re-injects TASKS.md',\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 the project uses external APIs, suggest sandbox.network.allowedDomains',\n '- If you detect a monorepo, suggest claudeMdExcludes in settings.json',\n ].join('\\n');\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 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 const hooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n const hookList = (hooks[event] as Record<string, unknown>[] | undefined) ?? [];\n\n const alreadyHas = hookList.some((g) => {\n const nested = g.hooks as Record<string, unknown>[] | undefined;\n return nested?.some((h) => String(h.command ?? \"\").includes(dedupKeyword));\n });\n if (alreadyHas) return false;\n\n const updatedList = prepend ? [entry, ...hookList] : [...hookList, entry];\n const updatedSettings = { ...settings, hooks: { ...hooks, [event]: updatedList } };\n await write(root, updatedSettings);\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.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 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: \"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: \"claude-launchpad memory push -y >/dev/null 2>&1 & exit 0\" }],\n }, false, `Added SessionEnd hook for memory sync to ${target}`);\n}\n\nexport async function removeStaleStopHook(root: string): Promise<boolean> {\n const settings = await readSettingsJson(root);\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\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.allowedMcpServers) return false;\n const other = placement === \"local\" ? await readSettingsJson(root) : await readSettingsLocalJson(root);\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"],"mappings":"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AA,IACA;AAAA,IACA;AAAA,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;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IA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","names":["readFile","readFile","writeFile","mkdir","access","join","join","join","readFile","join","join","readFile","join","readFile","writeFile","mkdir","access"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/memory/subcommands/install.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { createDatabase, closeDatabase } from '../storage/database.js';\nimport { migrate } from '../storage/migrator.js';\nimport { loadConfig, resolveDataDir } from '../config.js';\nimport { readSettingsJson, writeSettingsJson, readSettingsLocalJson, writeSettingsLocalJson } from '../../../lib/settings.js';\nimport { getMemoryPlacement } from '../../../lib/memory-placement.js';\nimport { log } from '../../../lib/output.js';\nimport type { MemoryPlacement } from '../../../types/index.js';\n\nfunction isGhAuthenticated(): boolean {\n try {\n execSync('gh auth status', { stdio: 'pipe', timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\ninterface InstallOpts {\n readonly dbPath?: string;\n}\n\nexport async function runInstall(opts: InstallOpts): Promise<void> {\n log.blank();\n log.step('Setting up your knowledge base');\n log.blank();\n\n // Step 0: Ensure native deps are installed globally\n await ensureNativeDeps();\n\n // Prompt for placement before any config writes\n const placement = await getMemoryPlacement(process.cwd());\n\n const config = loadConfig(opts.dbPath ? { dataDir: opts.dbPath } : undefined);\n const dataDir = resolveDataDir(config.dataDir);\n\n // Step 1: Database\n log.step('[1/5] Creating knowledge base...');\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n const db = createDatabase({ dataDir });\n migrate(db);\n closeDatabase(db);\n log.success(`Knowledge base created at ${dataDir}/memory.db`);\n\n // Step 2: Configure Claude Code settings\n log.step('[2/5] Connecting to Claude Code...');\n await configureSettings(process.cwd(), placement);\n\n // Step 3: Register MCP server (project scope for shared, local scope for local)\n log.step('[3/5] Enabling memory tools...');\n const mcpScope = placement === \"local\" ? \"local\" : \"project\";\n const registered = registerMcpServer(mcpScope);\n if (registered) {\n log.success('Memory tools available in Claude Code');\n } else {\n log.warn('Could not enable memory tools automatically.');\n log.info(`Run: claude mcp add --scope ${mcpScope} agentic-memory -- npx claude-launchpad memory serve`);\n }\n\n // Step 4: CLAUDE.md + skills\n log.step('[4/5] Adding instructions...');\n const guidanceAdded = injectClaudeMdGuidance(process.cwd(), placement);\n if (guidanceAdded) {\n const label = placement === \"local\" ? \".claude/CLAUDE.md\" : \"CLAUDE.md\";\n log.success(`${label} updated with memory instructions`);\n }\n if (placement === \"shared\") {\n const skillsInstalled = installSkills(process.cwd());\n if (skillsInstalled > 0) {\n log.success(`Installed ${skillsInstalled} skill(s) to .claude/skills/`);\n }\n }\n\n log.blank();\n log.success('Knowledge base is ready. Claude will now remember across sessions.');\n log.info('Restart your Claude Code session to activate.');\n\n // Sync guidance\n if (isGhAuthenticated()) {\n log.info('Cross-device sync available. Run `memory push` to back up, or it auto-syncs each session.');\n } else {\n log.blank();\n log.info('Recommended: install the GitHub CLI for cross-device memory sync:');\n log.step(' https://cli.github.com/');\n log.step(' gh auth login');\n }\n log.blank();\n}\n\nexport function detectExistingSetup(projectDir: string): MemoryPlacement | null {\n // Check local CLAUDE.md\n try {\n const localClaude = readFileSync(join(projectDir, '.claude', 'CLAUDE.md'), 'utf-8');\n if (localClaude.includes('## Memory') || localClaude.includes('agentic-memory')) return \"local\";\n } catch { /* not found */ }\n\n // Check root CLAUDE.md\n try {\n const rootClaude = readFileSync(join(projectDir, 'CLAUDE.md'), 'utf-8');\n if (rootClaude.includes('## Memory (agentic-memory)')) return \"shared\";\n } catch { /* not found */ }\n\n return null;\n}\n\nasync function configureSettings(projectDir: string, placement: MemoryPlacement): Promise<void> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(projectDir);\n\n // Disable built-in auto-memory\n log.info('Built-in auto-memory disabled (replaced by knowledge base)');\n\n // Build hooks immutably — always add sync hooks (they fail silently without gh)\n const baseHooks = (settings['hooks'] ?? {}) as Record<string, unknown[]>;\n const withPull = addSessionStartPullHook(baseHooks);\n const withContext = addSessionStartHook(withPull);\n const withPush = addSessionEndPushHook(withContext);\n\n // Build permissions immutably\n const withPermissions = addToolPermissions(settings);\n\n const updated = {\n ...withPermissions,\n autoMemoryEnabled: false,\n hooks: withPush,\n };\n\n await write(projectDir, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Claude Code configured in ${target}`);\n}\n\nfunction addSessionStartPullHook(hooks: Record<string, unknown[]>): Record<string, unknown[]> {\n const sessionStartHooks = (hooks['SessionStart'] ?? []) as Record<string, unknown>[];\n const alreadyHooked = sessionStartHooks.some((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 pull'),\n );\n });\n\n if (alreadyHooked) return hooks;\n\n // Insert at the beginning so pull runs before context injection\n const entry = {\n matcher: 'startup',\n hooks: [{ type: 'command', command: 'claude-launchpad memory pull -y 2>/dev/null; exit 0' }],\n };\n log.info('Session start: memories will auto-pull from GitHub Gist');\n return { ...hooks, SessionStart: [entry, ...sessionStartHooks] };\n}\n\nfunction addSessionStartHook(hooks: Record<string, unknown[]>): Record<string, unknown[]> {\n const sessionStartHooks = (hooks['SessionStart'] ?? []) as Record<string, unknown>[];\n const hookCommand = 'npx claude-launchpad memory context --json 2>/dev/null; exit 0';\n\n const alreadyHooked = sessionStartHooks.some((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('claude-launchpad memory context'),\n );\n });\n\n if (alreadyHooked) return hooks;\n\n const entry = {\n matcher: 'startup|resume',\n hooks: [{ type: 'command', command: hookCommand }],\n };\n log.info('Session start: Claude will recall relevant context automatically');\n return { ...hooks, SessionStart: [...sessionStartHooks, entry] };\n}\n\nfunction addSessionEndPushHook(hooks: Record<string, unknown[]>): Record<string, unknown[]> {\n const sessionEndHooks = (hooks['SessionEnd'] ?? []) as Record<string, unknown>[];\n const alreadyHooked = sessionEndHooks.some((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 push'),\n );\n });\n\n if (alreadyHooked) return hooks;\n\n const entry = {\n hooks: [{ type: 'command', command: 'claude-launchpad memory push -y >/dev/null 2>&1 & exit 0' }],\n };\n log.info('Session end: memories will auto-push to GitHub Gist');\n return { ...hooks, SessionEnd: [...sessionEndHooks, entry] };\n}\n\nfunction addToolPermissions(settings: Record<string, unknown>): Record<string, unknown> {\n const permissions = (settings['permissions'] ?? {}) as Record<string, unknown>;\n const allowList = (permissions['allow'] ?? []) as readonly string[];\n\n const memoryTools = [\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 = memoryTools.filter((t) => !allowList.includes(t));\n if (missing.length === 0) return settings;\n\n log.info(`${missing.length} memory tools auto-approved`);\n return {\n ...settings,\n permissions: { ...permissions, allow: [...allowList, ...missing] },\n };\n}\n\nasync function ensureNativeDeps(): Promise<void> {\n const { cwdRequire } = await import('../utils/require-deps.js');\n try {\n cwdRequire('better-sqlite3');\n return;\n } catch {\n // Not installed — install globally\n }\n\n log.step('Installing required database libraries...');\n try {\n execSync('npm install -g better-sqlite3 sqlite-vec', { stdio: 'pipe', timeout: 120000 });\n log.success('Database libraries installed');\n } catch {\n log.error('Could not install database libraries automatically.');\n log.blank();\n log.info('Install manually:');\n log.step(' npm install -g better-sqlite3 sqlite-vec');\n log.blank();\n log.info('Requires a C++ compiler (Xcode on macOS, build-essential on Linux).');\n process.exit(1);\n }\n}\n\nfunction registerMcpServer(scope: \"project\" | \"local\"): boolean {\n try {\n const existing = execSync('claude mcp list', { stdio: 'pipe', timeout: 10000, encoding: 'utf-8' });\n if (existing.includes('agentic-memory')) {\n log.info('Memory tools already registered');\n return true;\n }\n execSync(\n `claude mcp add --scope ${scope} agentic-memory -- npx claude-launchpad memory serve`,\n { stdio: 'pipe', timeout: 10000 },\n );\n return true;\n } catch {\n return false;\n }\n}\n\nconst MEMORY_GUIDANCE = `\n## Memory (agentic-memory)\nThis project uses **agentic-memory** for persistent memory across sessions.\n- **DO NOT** use the built-in auto-memory system (~/.claude/projects/*/memory/)\n- Memory context is **automatically injected** at session start via SessionStart hook - no need to call memory_recent manually\n- Use \\`memory_search\\` to find specific memories by keyword\n- Use \\`memory_store\\` to save decisions, gotchas, and learnings worth remembering\n- Use \\`memory_stats\\` to check memory health\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`;\n\nfunction injectClaudeMdGuidance(projectDir: string, placement: MemoryPlacement): boolean {\n const claudeMdPath = placement === \"local\"\n ? join(projectDir, '.claude', 'CLAUDE.md')\n : join(projectDir, 'CLAUDE.md');\n\n let content = '';\n try {\n content = readFileSync(claudeMdPath, 'utf-8');\n } catch {\n if (placement !== \"local\") return false;\n // Create local .claude/CLAUDE.md\n mkdirSync(join(projectDir, '.claude'), { recursive: true });\n content = '# Local Claude Config\\n';\n }\n\n if (content.includes('## Memory (agentic-memory)')) {\n return false;\n }\n\n const updated = content.trimEnd() + '\\n' + MEMORY_GUIDANCE;\n writeFileSync(claudeMdPath, updated, 'utf-8');\n return true;\n}\n\nconst MIGRATE_MEMORY_SKILL = `---\nname: lp-migrate-memory\ndescription: Migrate legacy Claude Code auto-memory files (~/.claude/projects/*/memory/*.md) into agentic-memory. Use when setting up agentic-memory on a project that already has built-in memories.\nallowed-tools: Read, Glob, Grep, mcp__agentic-memory__memory_store, mcp__agentic-memory__memory_search\n---\n\n# Migrate Legacy Claude Code Memories\n\nMigrate memory files from Claude Code's built-in auto-memory system into agentic-memory.\n\n## Steps\n\n1. **Find legacy memory files** for this project:\n - Scan \\`~/.claude/projects/*/memory/*.md\\` for directories whose slug matches the current project path\n - The slug format is the absolute path with \\`/\\` replaced by \\`-\\` and leading \\`-\\` (e.g. \\`-Users-john-projects-myapp\\`)\n - Also check \\`~/.claude/projects/*/memory/team/*.md\\` for team memories\n\n2. **For each memory file found**, read it and parse:\n - YAML frontmatter: \\`name\\`, \\`description\\`, \\`type\\` (user/feedback/project/reference)\n - Body content (everything after the frontmatter closing \\`---\\`)\n - Skip \\`MEMORY.md\\` (it's just an index file, not a memory)\n\n3. **Before storing**, check for duplicates:\n - Call \\`memory_search\\` with the memory description or first 100 chars of content\n - If a close match exists (same topic), skip it and report\n\n4. **Map types and store** each memory via \\`memory_store\\`:\n - \\`user\\` -> type: \\`semantic\\`, tags: [\\`user\\`, \\`migrated\\`], importance: 0.7\n - \\`feedback\\` -> type: \\`semantic\\`, tags: [\\`feedback\\`, \\`migrated\\`], importance: 0.8\n - \\`project\\` -> type: \\`semantic\\`, tags: [\\`project\\`, \\`migrated\\`], importance: 0.6\n - \\`reference\\` -> type: \\`semantic\\`, tags: [\\`reference\\`, \\`migrated\\`], importance: 0.5\n - Use the frontmatter \\`name\\` as the title\n - Use the body content as the memory content\n - Set source: \\`import\\`\n - Adjust importance up/down based on the content (decisions and gotchas deserve higher importance)\n\n5. **Report results**: list what was migrated, what was skipped (duplicates), and what failed\n\n## Important\n\n- Do NOT delete the original files - the user can do that manually after verifying\n- Do NOT migrate content that is purely derived from code (architecture, file structure) - it belongs in CLAUDE.md, not memory\n- If unsure about a memory's value, migrate it anyway - the decay system will naturally prune low-value memories over time\n`;\n\nconst SKILLS: Readonly<Record<string, string>> = {\n 'lp-migrate-memory': MIGRATE_MEMORY_SKILL,\n};\n\nfunction installSkills(projectDir: string): number {\n const skillsDir = join(projectDir, '.claude', 'skills');\n let installed = 0;\n\n for (const [name, content] of Object.entries(SKILLS)) {\n const skillDir = join(skillsDir, name);\n const skillPath = join(skillDir, 'SKILL.md');\n\n if (existsSync(skillPath)) continue;\n\n mkdirSync(skillDir, { recursive: true });\n writeFileSync(skillPath, content.trimStart(), 'utf-8');\n installed++;\n }\n\n return installed;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/memory/subcommands/push.ts"],"sourcesContent":["import { hostname } from 'node:os';\nimport { confirm } from '@inquirer/prompts';\nimport { log } from '../../../lib/output.js';\nimport { initStorage } from './init-storage.js';\nimport type { StorageContext } from './init-storage.js';\nimport {\n assertGhAvailable,\n loadSyncConfig,\n createGist,\n readGistFile,\n updateGistFiles,\n projectToFilename,\n} from '../utils/gist-transport.js';\nimport { mergeFromRemote, memoryToSyncRow, parsePayload } from '../utils/sync-merge.js';\nimport type { Memory, SyncPayload, SyncRelationRow } from '../types.js';\nimport { detectProject } from '../utils/project.js';\n\ninterface PushOpts {\n readonly all?: boolean;\n readonly yes?: boolean;\n}\n\nfunction buildPayload(\n memories: readonly ReturnType<typeof memoryToSyncRow>[],\n relations: readonly SyncRelationRow[],\n): SyncPayload {\n return {\n version: 1,\n machine_id: hostname(),\n pushed_at: new Date().toISOString(),\n memories,\n relations,\n };\n}\n\nfunction filterRelations(\n allRelations: readonly { sourceId: string; targetId: string; relationType: string; createdAt: string }[],\n memoryIds: ReadonlySet<string>,\n): readonly SyncRelationRow[] {\n return allRelations\n .filter((r) => memoryIds.has(r.sourceId) && memoryIds.has(r.targetId))\n .map((r) => ({\n source_id: r.sourceId,\n target_id: r.targetId,\n relation_type: r.relationType as SyncRelationRow['relation_type'],\n created_at: r.createdAt,\n }));\n}\n\nexport async function runPush(opts: PushOpts): Promise<void> {\n assertGhAvailable();\n\n const { requireMemoryDeps } = await import('../utils/require-deps.js');\n await requireMemoryDeps();\n const ctx = initStorage();\n\n try {\n const syncConfig = loadSyncConfig();\n const allRelations = ctx.relationRepo.getAll();\n\n if (opts.all) {\n await pushAll(ctx, allRelations, syncConfig, opts);\n } else {\n await pushProject(ctx, allRelations, syncConfig, opts);\n }\n } finally {\n ctx.close();\n }\n}\n\nasync function pushProject(\n ctx: StorageContext,\n allRelations: readonly { sourceId: string; targetId: string; relationType: string; createdAt: string }[],\n syncConfig: { gistId: string } | null,\n opts: PushOpts,\n): Promise<void> {\n const project = detectProject(process.cwd());\n if (!project) {\n log.error('Could not detect project. Run from a project directory or use --all.');\n return;\n }\n\n const filename = projectToFilename(project);\n\n // Pull-before-push for this project\n if (syncConfig) {\n const remote = parsePayload(readGistFile(syncConfig.gistId, filename));\n if (remote) mergeFromRemote(ctx.memoryRepo, ctx.relationRepo, remote);\n }\n\n const memories = ctx.memoryRepo.getAllForSync(project);\n\n if (memories.length === 0) {\n log.warn(`No memories found for \"${project}\". Nothing to push.`);\n return;\n }\n\n const memoryIds = new Set(memories.map((m) => m.id));\n const relations = filterRelations(allRelations, memoryIds);\n const json = JSON.stringify(buildPayload(memories.map(memoryToSyncRow), relations), null, 2);\n\n if (!syncConfig) {\n if (!opts.yes && !(await confirmCreate())) return;\n createGist(filename, json);\n } else {\n updateGistFiles(syncConfig.gistId, { [filename]: json });\n }\n\n log.blank();\n log.step('Push complete');\n log.info(`Project: ${project} (${memories.length} memories)`);\n log.info(`Relations: ${relations.length}`);\n log.blank();\n}\n\nasync function pushAll(\n ctx: StorageContext,\n allRelations: readonly { sourceId: string; targetId: string; relationType: string; createdAt: string }[],\n syncConfig: { gistId: string } | null,\n opts: PushOpts,\n): Promise<void> {\n const allMemories = ctx.memoryRepo.getAllForSync();\n\n if (allMemories.length === 0) {\n log.warn('No memories found. Nothing to push.');\n return;\n }\n\n const byProject = groupByProject(allMemories);\n\n const files: Record<string, string> = {};\n for (const [project, memories] of byProject) {\n const memoryIds = new Set(memories.map((m) => m.id));\n const relations = filterRelations(allRelations, memoryIds);\n files[projectToFilename(project)] = JSON.stringify(\n buildPayload(memories.map(memoryToSyncRow), relations), null, 2,\n );\n }\n\n if (!syncConfig) {\n if (!opts.yes && !(await confirmCreate())) return;\n const entries = Object.entries(files);\n const gistId = createGist(entries[0]![0], entries[0]![1]);\n if (entries.length > 1) {\n updateGistFiles(gistId, Object.fromEntries(entries.slice(1)));\n }\n } else {\n updateGistFiles(syncConfig.gistId, files);\n }\n\n log.blank();\n log.step('Push complete');\n log.info(`Projects: ${byProject.size}`);\n log.info(`Memories: ${allMemories.length}`);\n log.blank();\n}\n\nfunction groupByProject(memories: readonly Memory[]): Map<string, Memory[]> {\n const byProject = new Map<string, Memory[]>();\n for (const m of memories) {\n const key = m.project ?? '_global';\n const list = byProject.get(key) ?? [];\n list.push(m);\n byProject.set(key, list);\n }\n return byProject;\n}\n\nasync function confirmCreate(): Promise<boolean> {\n const proceed = await confirm({\n message: 'Create a private GitHub Gist for memory sync?',\n default: true,\n });\n if (!proceed) log.info('Skipped.');\n return proceed;\n}\n"],"mappings":"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","names":[]}