From 0db0b2f26e38fe74c89be0b85bc521bc4bb6b3ed Mon Sep 17 00:00:00 2001 From: Tony Casey Date: Thu, 12 Feb 2026 11:28:32 +0000 Subject: [PATCH] refactor(infrastructure): consolidate skills service factories (LISA-58) Move skill service factories (MemoryService, TaskService, PromptService) from skills/shared to infrastructure layer. This eliminates duplicate code between skills and infrastructure while maintaining backwards compatibility through re-exports. Changes: - Create shared GitMemFactory with lazy singleton pattern - Move skill services to infrastructure/services/ - Move skill interfaces to infrastructure/services/skill-interfaces/ - Update bootstrap.ts to use shared git-mem instance - Re-export from skills/shared for backwards compatibility - Delete 6 duplicate files (-1341 lines) Skills entry points continue to work unchanged via re-exports. Co-Authored-By: Claude Opus 4.5 --- src/lib/infrastructure/di/bootstrap.ts | 17 +++--- .../infrastructure/git-mem/GitMemFactory.ts | 56 +++++++++++++++++++ src/lib/infrastructure/git-mem/index.ts | 1 + .../services/SkillMemoryService.ts} | 29 +++++----- .../services/SkillPromptService.ts} | 45 ++++++--------- .../services/SkillTaskService.ts} | 27 +++++---- src/lib/infrastructure/services/index.ts | 19 +++++++ .../skill-interfaces/ISkillMemoryService.ts} | 15 +++-- .../skill-interfaces/ISkillPromptService.ts | 48 ++++++++++++++++ .../skill-interfaces/ISkillTaskService.ts} | 14 +++-- .../services/skill-interfaces/index.ts | 54 ++++++++++++++++++ .../skills/shared/clients/GitMemFactory.ts | 17 ------ src/lib/skills/shared/clients/index.ts | 6 +- src/lib/skills/shared/services/index.ts | 31 ++++++---- .../shared/services/interfaces/index.ts | 6 +- 15 files changed, 282 insertions(+), 103 deletions(-) create mode 100644 src/lib/infrastructure/git-mem/GitMemFactory.ts rename src/lib/{skills/shared/services/MemoryService.ts => infrastructure/services/SkillMemoryService.ts} (92%) rename src/lib/{skills/shared/services/PromptService.ts => infrastructure/services/SkillPromptService.ts} (62%) rename src/lib/{skills/shared/services/TaskService.ts => infrastructure/services/SkillTaskService.ts} (93%) rename src/lib/{skills/shared/services/interfaces/IMemoryService.ts => infrastructure/services/skill-interfaces/ISkillMemoryService.ts} (91%) create mode 100644 src/lib/infrastructure/services/skill-interfaces/ISkillPromptService.ts rename src/lib/{skills/shared/services/interfaces/ITaskService.ts => infrastructure/services/skill-interfaces/ISkillTaskService.ts} (92%) create mode 100644 src/lib/infrastructure/services/skill-interfaces/index.ts delete mode 100644 src/lib/skills/shared/clients/GitMemFactory.ts diff --git a/src/lib/infrastructure/di/bootstrap.ts b/src/lib/infrastructure/di/bootstrap.ts index cb58565..fa7b25c 100644 --- a/src/lib/infrastructure/di/bootstrap.ts +++ b/src/lib/infrastructure/di/bootstrap.ts @@ -56,8 +56,8 @@ import { createTranscriptEnricher } from '../services/TranscriptEnricher'; import type { ISummarizationService } from '../../domain/interfaces/ISummarizationService'; import { createLogger, createNullLogger } from '../logging'; -// git-mem imports -import { MemoryService as GitMemService, NotesService, MemoryRepository } from 'git-mem/dist/index'; +// git-mem factory (shared singleton) +import { getGitMemInstance } from '../git-mem'; /** * Result of bootstrapping the container. @@ -106,13 +106,11 @@ export async function bootstrapContainer(config: IServiceConfig = {}): Promise; -} - -export interface IPromptServiceDependencies { +/** + * Dependencies for creating a skill prompt service. + */ +export interface ISkillPromptServiceDependencies { gitMem: IGitMemMemoryService; } /** - * Creates a prompt service instance backed by git-mem. + * Creates a skill prompt service instance backed by git-mem. + * + * @param deps - Service dependencies + * @returns Skill prompt service implementation */ -export function createPromptService(deps: IPromptServiceDependencies): IPromptService { +export function createSkillPromptService(deps: ISkillPromptServiceDependencies): ISkillPromptService { const { gitMem } = deps; return { diff --git a/src/lib/skills/shared/services/TaskService.ts b/src/lib/infrastructure/services/SkillTaskService.ts similarity index 93% rename from src/lib/skills/shared/services/TaskService.ts rename to src/lib/infrastructure/services/SkillTaskService.ts index f85c81d..e2e8511 100644 --- a/src/lib/skills/shared/services/TaskService.ts +++ b/src/lib/infrastructure/services/SkillTaskService.ts @@ -1,24 +1,27 @@ /** * Task service implementation for skill scripts. * Uses git-mem for all task operations. + * + * This is the "rich" task service with full CLI capabilities: + * list, add, update, link, unlink, listLinked. */ import type { IMemoryService as IGitMemMemoryService } from 'git-mem/dist/index'; import type { - ITaskService, - ITask, + ISkillTaskService, + ISkillTask, ITaskListResult, ITaskWriteResult, ITaskWriteOptions, + ITaskLoadOptions, ITaskLinkResult, ITaskExternalLink, ExternalLinkSource, - ITaskLoadOptions, -} from './interfaces'; +} from './skill-interfaces'; /** - * Dependencies for creating a task service. + * Dependencies for creating a skill task service. */ -export interface ITaskServiceDependencies { +export interface ISkillTaskServiceDependencies { gitMem: IGitMemMemoryService; } @@ -36,16 +39,16 @@ function parseTaskContent(content: string): Record | null { } /** - * Creates a task service instance backed by git-mem. + * Creates a skill task service instance backed by git-mem. * * Tasks are stored as git-mem memories with: * - Tags: `task`, `group:`, `status:`, `task_id:` * - Content: JSON `{ type: "task", title, status, repo, assignee, ... }` * * @param deps - Service dependencies - * @returns Task service implementation + * @returns Skill task service implementation */ -export function createTaskService(deps: ITaskServiceDependencies): ITaskService { +export function createSkillTaskService(deps: ISkillTaskServiceDependencies): ISkillTaskService { const { gitMem } = deps; return { @@ -78,12 +81,12 @@ export function createTaskService(deps: ITaskServiceDependencies): ITaskService // Apply limit filtered = filtered.slice(0, limit); - // Map to ITask - const tasks: ITask[] = filtered.map(m => { + // Map to ISkillTask + const tasks: ISkillTask[] = filtered.map(m => { const taskObj = parseTaskContent(m.content); if (taskObj) { - const task: ITask = { + const task: ISkillTask = { title: String(taskObj.title || ''), status: String(taskObj.status || 'unknown'), repo: String(taskObj.repo || defaultRepo), diff --git a/src/lib/infrastructure/services/index.ts b/src/lib/infrastructure/services/index.ts index 87285e9..4068db1 100644 --- a/src/lib/infrastructure/services/index.ts +++ b/src/lib/infrastructure/services/index.ts @@ -2,8 +2,27 @@ * Infrastructure service implementations. */ +// Domain-level git-mem services (simpler interface for DI/hooks) export { GitMemMemoryService } from './GitMemMemoryService'; export { GitMemTaskService } from './GitMemTaskService'; + +// Skill-level git-mem services (rich interface for CLI scripts) +export { + createSkillMemoryService, + type ISkillMemoryServiceDependencies, +} from './SkillMemoryService'; +export { + createSkillTaskService, + type ISkillTaskServiceDependencies, +} from './SkillTaskService'; +export { + createSkillPromptService, + type ISkillPromptServiceDependencies, +} from './SkillPromptService'; + +// Skill interfaces (re-export for convenience) +export * from './skill-interfaces'; + export { EventEmitter } from './EventEmitter'; export { SessionCaptureService } from './SessionCaptureService'; export { RecursionService } from './RecursionService'; diff --git a/src/lib/skills/shared/services/interfaces/IMemoryService.ts b/src/lib/infrastructure/services/skill-interfaces/ISkillMemoryService.ts similarity index 91% rename from src/lib/skills/shared/services/interfaces/IMemoryService.ts rename to src/lib/infrastructure/services/skill-interfaces/ISkillMemoryService.ts index b7cc8ac..069ade2 100644 --- a/src/lib/skills/shared/services/interfaces/IMemoryService.ts +++ b/src/lib/infrastructure/services/skill-interfaces/ISkillMemoryService.ts @@ -1,9 +1,12 @@ /** * Memory service interface for skill scripts. * Provides a clean API for memory/fact CRUD operations. + * + * This is the "rich" memory interface used by CLI scripts, + * with operations like dedupe, curate, conflicts, consolidate. */ -import type { CurationMark } from '../../../../domain/interfaces/ICurationService'; -import type { ConsolidationAction } from '../../../../domain/interfaces/IConsolidationService'; +import type { CurationMark } from '../../../domain/interfaces/ICurationService'; +import type { ConsolidationAction } from '../../../domain/interfaces/IConsolidationService'; /** * A memory/fact item. @@ -166,9 +169,13 @@ export interface IMemoryConsolidateResult { } /** - * Memory service interface. + * Memory service interface for skill scripts. + * + * This is the "rich" interface with full CLI capabilities. + * Contrast with IMemoryService in domain/interfaces which is + * the simpler infrastructure interface. */ -export interface IMemoryService { +export interface ISkillMemoryService { /** * Load memories/facts from storage. * diff --git a/src/lib/infrastructure/services/skill-interfaces/ISkillPromptService.ts b/src/lib/infrastructure/services/skill-interfaces/ISkillPromptService.ts new file mode 100644 index 0000000..188c249 --- /dev/null +++ b/src/lib/infrastructure/services/skill-interfaces/ISkillPromptService.ts @@ -0,0 +1,48 @@ +/** + * Prompt service interface for skill scripts. + * Captures user prompts to git-mem with deduplication. + */ + +/** + * Arguments for adding a prompt. + */ +export interface IPromptArgs { + text: string; + role?: string; + source?: string; + force?: boolean; + groupId: string; +} + +/** + * Result of a prompt add operation. + */ +export interface IPromptResult { + status: 'ok' | 'skipped'; + action?: 'add'; + group?: string; + role?: string; + source?: string; + reason?: string; +} + +/** + * Prompt service interface. + */ +export interface ISkillPromptService { + /** + * Generate a fingerprint for deduplication. + * + * @param text - The prompt text to fingerprint + * @returns SHA1-based fingerprint (first 16 chars) + */ + fingerprint(text: string): string; + + /** + * Add a prompt to memory. + * + * @param args - Prompt arguments + * @returns Result indicating success or skip (duplicate) + */ + addPrompt(args: IPromptArgs): Promise; +} diff --git a/src/lib/skills/shared/services/interfaces/ITaskService.ts b/src/lib/infrastructure/services/skill-interfaces/ISkillTaskService.ts similarity index 92% rename from src/lib/skills/shared/services/interfaces/ITaskService.ts rename to src/lib/infrastructure/services/skill-interfaces/ISkillTaskService.ts index ed565ee..0fa19e8 100644 --- a/src/lib/skills/shared/services/interfaces/ITaskService.ts +++ b/src/lib/infrastructure/services/skill-interfaces/ISkillTaskService.ts @@ -1,6 +1,9 @@ /** * Task service interface for skill scripts. * Provides a clean API for task CRUD operations. + * + * This is the "rich" task interface used by CLI scripts, + * with operations like external linking (GitHub, Jira, Linear). */ /** @@ -26,7 +29,7 @@ export interface ITaskExternalLink { /** * A task item. */ -export interface ITask { +export interface ISkillTask { title: string; status: string; repo: string; @@ -46,7 +49,7 @@ export interface ITaskListResult { action: 'list'; group: string; groups: string[]; - tasks: ITask[]; + tasks: ISkillTask[]; mode: TaskMode; } @@ -108,9 +111,12 @@ export interface ITaskLinkResult { } /** - * Task service interface. + * Task service interface for skill scripts. + * + * This is the "rich" interface with full CLI capabilities + * including external system linking. */ -export interface ITaskService { +export interface ISkillTaskService { /** * List tasks from storage. * diff --git a/src/lib/infrastructure/services/skill-interfaces/index.ts b/src/lib/infrastructure/services/skill-interfaces/index.ts new file mode 100644 index 0000000..3d05c00 --- /dev/null +++ b/src/lib/infrastructure/services/skill-interfaces/index.ts @@ -0,0 +1,54 @@ +/** + * Skill service interfaces. + * + * These are the "rich" interfaces used by CLI skill scripts, + * with full capabilities like dedupe, curate, external linking, etc. + * + * Contrast with domain/interfaces which has simpler infrastructure interfaces. + */ + +export type { + // Memory types + IFact, + MemoryMode, + IMemoryLoadResult, + IMemoryAddResult, + IMemoryAddOptions, + IMemoryLoadOptions, + IMemoryExpireResult, + IMemoryCleanupResult, + IConflictGroup, + IMemoryConflictsResult, + IDuplicateGroup, + IMemoryDedupeResult, + IMemoryCurateResult, + IMemoryConsolidateResult, + ISkillMemoryService, +} from './ISkillMemoryService'; + +export type { + // Task types + TaskMode, + ExternalLinkSource, + ITaskExternalLink, + ISkillTask, + ITaskListResult, + ITaskWriteResult, + ITaskWriteOptions, + ITaskLoadOptions, + ITaskLinkResult, + ISkillTaskService, +} from './ISkillTaskService'; + +export type { + // Prompt types + IPromptArgs, + IPromptResult, + ISkillPromptService, +} from './ISkillPromptService'; + +// Re-export with legacy names for backwards compatibility +export type { ISkillMemoryService as IMemoryService } from './ISkillMemoryService'; +export type { ISkillTaskService as ITaskService } from './ISkillTaskService'; +export type { ISkillTask as ITask } from './ISkillTaskService'; +export type { ISkillPromptService as IPromptService } from './ISkillPromptService'; diff --git a/src/lib/skills/shared/clients/GitMemFactory.ts b/src/lib/skills/shared/clients/GitMemFactory.ts deleted file mode 100644 index cbe6038..0000000 --- a/src/lib/skills/shared/clients/GitMemFactory.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Factory for creating git-mem service instances in skill scripts. - * - * Centralises the git-mem wiring so every skill entry point - * can call `createGitMem()` instead of repeating the setup. - */ -import { MemoryService, NotesService, MemoryRepository } from 'git-mem/dist/index'; -import type { IMemoryService } from 'git-mem/dist/index'; - -/** - * Create a git-mem MemoryService wired to the current repo's git notes. - */ -export function createGitMem(): IMemoryService { - const notes = new NotesService(); - const repo = new MemoryRepository(notes); - return new MemoryService(repo); -} diff --git a/src/lib/skills/shared/clients/index.ts b/src/lib/skills/shared/clients/index.ts index b21e80b..bb466ec 100644 --- a/src/lib/skills/shared/clients/index.ts +++ b/src/lib/skills/shared/clients/index.ts @@ -1,10 +1,14 @@ /** * Client implementations and interfaces for backend connections. + * + * The git-mem factory is now consolidated in infrastructure. + * This file re-exports it for backwards compatibility. */ // Re-export interfaces export * from './interfaces'; // Export client factories -export { createGitMem } from './GitMemFactory'; +// createGitMem is re-exported from infrastructure for backwards compatibility +export { createGitMem } from '../../../infrastructure/git-mem'; export { createGhCliClient, createGhCliClientFromEnv } from './GhCliClient'; diff --git a/src/lib/skills/shared/services/index.ts b/src/lib/skills/shared/services/index.ts index 250f81c..74ea131 100644 --- a/src/lib/skills/shared/services/index.ts +++ b/src/lib/skills/shared/services/index.ts @@ -1,13 +1,27 @@ /** * Shared service implementations for skill scripts. + * + * Core data services (MemoryService, TaskService, PromptService) are now + * consolidated in infrastructure. This file re-exports them for backwards + * compatibility with existing skill entry points. */ -// Re-export interfaces -export * from './interfaces'; +// Re-export interfaces from infrastructure +export * from '../../../infrastructure/services/skill-interfaces'; -// Core data services -export { createTaskService, type ITaskServiceDependencies } from './TaskService'; -export { createMemoryService, type IMemoryServiceDependencies } from './MemoryService'; +// Core data services (re-exported from infrastructure) +export { + createSkillTaskService as createTaskService, + type ISkillTaskServiceDependencies as ITaskServiceDependencies, +} from '../../../infrastructure/services/SkillTaskService'; +export { + createSkillMemoryService as createMemoryService, + type ISkillMemoryServiceDependencies as IMemoryServiceDependencies, +} from '../../../infrastructure/services/SkillMemoryService'; +export { + createSkillPromptService as createPromptService, + type ISkillPromptServiceDependencies as IPromptServiceDependencies, +} from '../../../infrastructure/services/SkillPromptService'; // CLI services export { @@ -56,12 +70,7 @@ export { type ICompileResult, type IMergeResult, } from './SkillCompilerService'; -export { - createPromptService, - type IPromptService, - type IPromptArgs, - type IPromptResult, -} from './PromptService'; +// PromptService is now re-exported from infrastructure (see above) export { createInitReviewService, type IInitReviewService, diff --git a/src/lib/skills/shared/services/interfaces/index.ts b/src/lib/skills/shared/services/interfaces/index.ts index c8dce0e..afeaa1a 100644 --- a/src/lib/skills/shared/services/interfaces/index.ts +++ b/src/lib/skills/shared/services/interfaces/index.ts @@ -1,5 +1,7 @@ /** * Service interfaces for skill scripts. + * + * These interfaces are now consolidated in infrastructure. + * This file re-exports them for backwards compatibility. */ -export * from './ITaskService'; -export * from './IMemoryService'; +export * from '../../../../infrastructure/services/skill-interfaces';