diff --git a/cli/src/commands/install.ts b/cli/src/commands/install.ts index fb268d2..5f0de74 100644 --- a/cli/src/commands/install.ts +++ b/cli/src/commands/install.ts @@ -94,6 +94,26 @@ const IDE_CONFIGS: Record = { common: { commandsDir: '.agents/commands', skillsDir: '.agents/skills' }, }; +// Entry file templates configuration +const ENTRY_TEMPLATES = { + AGENTS: { + template: 'AGENTS.md.template', + output: 'AGENTS.md', + displayName: 'AGENTS.md (通用入口文件)', + }, + CLAUDE: { + template: 'CLAUDE.md.template', + output: 'CLAUDE.md', + displayName: 'CLAUDE.md (Claude Code 入口文件)', + }, + CURSOR: { + template: 'cursor-rule.mdc.template', + outputDir: '.cursor/rules', + output: 'openmemory.mdc', + displayName: '.cursor/rules/openmemory.mdc (Cursor 规则文件)', + }, +} as const; + const BANNER = ` ╔═══════════════════════════════════════════════════════════════╗ ║ ║ @@ -389,11 +409,101 @@ agent: `; } -function processTemplate(content: string, projectName: string): string { +function processTemplate(content: string, projectName: string, ideList?: string[]): string { const now = new Date().toISOString().split('T')[0]; // YYYY-MM-DD return content .replace(/\{\{PROJECT_NAME\}\}/g, projectName) - .replace(/\{\{CREATED_AT\}\}/g, now); + .replace(/\{\{CREATED_AT\}\}/g, now) + .replace(/\{\{IDE_LIST\}\}/g, ideList?.join(', ') || 'common'); +} + +// ============================================================================ +// Entry File Generation +// ============================================================================ + +/** + * Generate entry files (AGENTS.md, CLAUDE.md, etc.) based on selected IDEs + * Entry files are what AI agents read at startup to understand the project + */ +function generateEntryFiles( + targetDir: string, + projectName: string, + selectedIdes: string[], + templatesDir: string, + force: boolean +): void { + const entryTemplatesDir = join(templatesDir, 'entry'); + + // Check if entry templates exist + if (!existsSync(entryTemplatesDir)) { + console.log(chalk.yellow(' ⚠ 入口文件模板不存在,跳过生成')); + return; + } + + // Helper function to safely generate entry file + const generateFile = ( + templatePath: string, + targetPath: string, + displayName: string, + createDir?: string + ): void => { + try { + if (!existsSync(templatePath)) { + return; + } + + if (!existsSync(targetPath) || force) { + if (createDir) { + mkdirSync(createDir, { recursive: true }); + } + const template = readFileSync(templatePath, 'utf-8'); + const content = processTemplate(template, projectName, selectedIdes); + writeFileSync(targetPath, content); + console.log(chalk.green(` ✓ 创建 ${displayName}`)); + } else { + console.log(chalk.gray(` ○ ${displayName} 已存在 (使用 --force 覆盖)`)); + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + console.log(chalk.red(` ✗ 创建 ${displayName} 失败: ${errorMessage}`)); + } + }; + + // Always generate AGENTS.md (universal entry file) + generateFile( + join(entryTemplatesDir, ENTRY_TEMPLATES.AGENTS.template), + join(targetDir, ENTRY_TEMPLATES.AGENTS.output), + ENTRY_TEMPLATES.AGENTS.displayName + ); + + // Generate IDE-specific entry files + for (const ide of selectedIdes) { + switch (ide) { + case 'claude': + case 'claude-desktop': + generateFile( + join(entryTemplatesDir, ENTRY_TEMPLATES.CLAUDE.template), + join(targetDir, ENTRY_TEMPLATES.CLAUDE.output), + ENTRY_TEMPLATES.CLAUDE.displayName + ); + break; + + case 'cursor': { + const cursorRulesDir = join(targetDir, ENTRY_TEMPLATES.CURSOR.outputDir); + generateFile( + join(entryTemplatesDir, ENTRY_TEMPLATES.CURSOR.template), + join(cursorRulesDir, ENTRY_TEMPLATES.CURSOR.output), + ENTRY_TEMPLATES.CURSOR.displayName, + cursorRulesDir + ); + break; + } + + // augment, gemini, common use AGENTS.md only (already generated above) + default: + break; + } + } } // ============================================================================ @@ -954,6 +1064,10 @@ async function phase2_initProject(options: InstallOptions): Promise { console.log(chalk.green(` ✓ 配置 ${ide} (${config.commandsDir}/)`)); } + // Generate entry files (AGENTS.md, CLAUDE.md, etc.) + console.log(chalk.bold('\n📄 生成入口文件...\n')); + generateEntryFiles(cwd, projectName, selectedIdes, templatesDir, shouldForce); + // Show summary for multi-select (Fix L2) if (selectedIdes.length > 1) { console.log(chalk.green(`\n ✓ 已为 ${selectedIdes.length} 个 IDE 配置完成: ${selectedIdes.join(', ')}`)); diff --git a/cli/templates/entry/AGENTS.md.template b/cli/templates/entry/AGENTS.md.template new file mode 100644 index 0000000..c4fa0bf --- /dev/null +++ b/cli/templates/entry/AGENTS.md.template @@ -0,0 +1,118 @@ +# {{PROJECT_NAME}} - Agent Instructions + +This project uses **OpenMemory Plus** for persistent agent memory management. + +--- + +## 🧠 Memory System (Auto-Enabled) + +> **Core Principle**: Agent automatically extracts memories without user intervention + +### Session Lifecycle + +#### 🚀 Session Start (Auto) + +1. **Load project context** + ``` + Read _omp/memory/project.yaml + Read _omp/memory/activeContext.md + ``` + +2. **Load user preferences** (if openmemory MCP available) + ``` + search_memory_openmemory: "user preferences for {{PROJECT_NAME}}" + ``` + +3. **Restore work state** + ``` + Read _omp/memory/progress.md + ``` + +#### ⚡ During Session - Auto-Extraction + +**When detecting trigger events, automatically dispatch memory-extraction subagent:** + +| Priority | Trigger | Detection Signal | Storage | +|----------|---------|------------------|---------| +| P0 | Task complete | Task marked complete | `progress.md` | +| P0 | Tech decision | "decide/choose/use" or "决定/选择/采用" | `decisions.yaml` | +| P1 | Config change | .env, config file modified | `project.yaml` | +| P1 | Deployment | deploy/vercel/wrangler output | `project.yaml` | +| P2 | User preference | "I prefer/like" or "我喜欢/偏好" | `openmemory` | +| P2 | Architecture | "pattern/architecture/design" | `systemPatterns.md` | +| P3 | Checkpoint | Every 10 exchanges | `activeContext.md` | + +**Subagent dispatch template**: +``` +Use sub-agent-explore or Task tool: + name: memory-extract-{timestamp} + instruction: See _omp/skills/memory-extraction/subagent-prompt.md +``` + +#### 🏁 Session End (Auto) + +Dispatch final memory-extraction subagent: +- Session summary → `activeContext.md` +- Unextracted learnings → appropriate memory files +- Progress updates → `progress.md` + +--- + +## 📁 Project Structure + +``` +_omp/ # OpenMemory Plus core +├── commands/ # Agent commands +│ └── memory.md # /memory entry point +├── workflows/ # Multi-step workflows +│ └── memory/ # Memory management workflow +├── skills/ # Agent skills +│ └── memory-extraction/ # Auto-extract learnings +│ ├── SKILL.md # Skill definition +│ ├── subagent-prompt.md # Subagent dispatch template +│ └── triggers.md # Trigger definitions +└── memory/ # Project memory files + ├── project.yaml # Project config (SSOT) + ├── activeContext.md # Current session context + ├── productContext.md # Product/feature context + ├── progress.md # Development progress + ├── projectbrief.md # Project overview + ├── systemPatterns.md # Architecture patterns + ├── techContext.md # Technical decisions + └── decisions.yaml # Decision records +``` + +--- + +## 🎯 Manual Commands + +Use `/memory` for manual memory operations: + +| Command | Description | +|---------|-------------| +| `/memory` | Open memory management menu | +| `/memory save` | Force save current context | +| `/memory load` | Load specific memory file | +| `/memory search ` | Search through memories | +| `/memory sync` | Sync with external memory (Qdrant) | + +--- + +## ⚙️ Integration + +This project is configured for: {{IDE_LIST}} + +### Dual-Layer Memory Architecture + +| Layer | Storage | Purpose | +|-------|---------|---------| +| Project | `_omp/memory/` | Project config, decisions, progress | +| User | `openmemory` MCP | User preferences, cross-project context | + +### MCP Configuration + +For MCP setup, see your IDE-specific settings file or run: +```bash +npx openmemory-plus install --show-mcp +``` + diff --git a/cli/templates/entry/CLAUDE.md.template b/cli/templates/entry/CLAUDE.md.template new file mode 100644 index 0000000..ea964fd --- /dev/null +++ b/cli/templates/entry/CLAUDE.md.template @@ -0,0 +1,78 @@ +# {{PROJECT_NAME}} - Claude Code Instructions + +This project uses **OpenMemory Plus** for persistent memory management. + +--- + +## 🧠 Memory System (Auto-Enabled) + +> **Core Principle**: Agent automatically extracts memories without user intervention + +### Session Lifecycle + +**🚀 Session Start** - Auto-load: +``` +Read _omp/memory/project.yaml # Project config +Read _omp/memory/activeContext.md # Recent context +Search openmemory # User preferences +``` + +**⚡ During Session** - Auto-extraction triggers: + +| Trigger | Detection Signal | Storage | +|---------|------------------|---------| +| Task complete | Task marked complete | `progress.md` | +| Tech decision | "decide/choose" or "决定/选择" | `decisions.yaml` | +| Config change | .env/config modified | `project.yaml` | +| User preference | "I prefer" or "我喜欢" | `openmemory` | + +**🏁 Session End** - Auto-save: +- Session summary → `activeContext.md` +- Progress updates → `progress.md` + +--- + +## 📁 Project Memory (`_omp/memory/`) + +| File | Purpose | +|------|---------| +| `project.yaml` | Project config (SSOT) | +| `decisions.yaml` | Technical decisions | +| `activeContext.md` | Current working context | +| `productContext.md` | Product/feature requirements | +| `progress.md` | Development milestones | +| `projectbrief.md` | Project overview | +| `systemPatterns.md` | Architecture patterns | +| `techContext.md` | Technical stack info | + +--- + +## 🎯 Manual Commands + +Use `/memory` for manual operations: + +| Command | Description | +|---------|-------------| +| `/memory` | Open memory menu | +| `/memory save` | Force save context | +| `/memory search ` | Search memories | + +--- + +## 📍 Locations + +- Commands: `.claude/commands/` +- Skills: `.claude/skills/` +- Core: `_omp/` +- Subagent Prompt: `_omp/skills/memory-extraction/subagent-prompt.md` + +--- + +## ⚙️ MCP Integration + +Memory backed by Qdrant vector database via MCP. + +Config: `~/Library/Application Support/Claude/claude_desktop_config.json` + +Run for setup: `npx openmemory-plus install --show-mcp` + diff --git a/cli/templates/entry/cursor-rule.mdc.template b/cli/templates/entry/cursor-rule.mdc.template new file mode 100644 index 0000000..0cd747b --- /dev/null +++ b/cli/templates/entry/cursor-rule.mdc.template @@ -0,0 +1,36 @@ +--- +description: OpenMemory Plus - Agent Memory System +globs: ["**/*"] +alwaysApply: true +--- + +# {{PROJECT_NAME}} - Memory System + +This project uses **OpenMemory Plus** for persistent agent memory. + +## Quick Start + +``` +/memory +``` + +## Memory Files (`_omp/memory/`) + +- `activeContext.md` - Current session context +- `productContext.md` - Product requirements +- `progress.md` - Development progress +- `systemPatterns.md` - Architecture patterns +- `techContext.md` - Technical decisions + +## Workflow + +1. Load context: `@_omp/memory/activeContext.md` +2. Work on tasks with memory awareness +3. Save learnings with `/memory save` + +## Commands & Skills + +- Commands: `.cursor/commands/` +- Skills: `.cursor/skills/` +- Core: `_omp/` + diff --git a/cli/templates/shared/_omp/memory/decisions.yaml b/cli/templates/shared/_omp/memory/decisions.yaml new file mode 100644 index 0000000..7ace393 --- /dev/null +++ b/cli/templates/shared/_omp/memory/decisions.yaml @@ -0,0 +1,25 @@ +# Technical Decisions Log +# Auto-populated by memory-extraction subagent +# Format: YAML list of decision records +# +# Each decision should include: +# - id: Unique identifier (dec-YYYY-MM-DD-NNN) +# - date: When the decision was made +# - title: Brief description +# - context: Why this decision was needed +# - choice: What was chosen +# - alternatives: Other options considered +# - impact: Areas affected by this decision + +decisions: [] + +# Example entry (uncomment and modify): +# decisions: +# - id: dec-2026-02-03-001 +# date: 2026-02-03 +# title: "Package Manager Selection" +# context: "Need faster dependency installation" +# choice: "pnpm" +# alternatives: ["npm", "yarn"] +# impact: "All package commands use pnpm" + diff --git a/cli/templates/shared/_omp/skills/memory-extraction/subagent-prompt.md b/cli/templates/shared/_omp/skills/memory-extraction/subagent-prompt.md new file mode 100644 index 0000000..83ba7f9 --- /dev/null +++ b/cli/templates/shared/_omp/skills/memory-extraction/subagent-prompt.md @@ -0,0 +1,145 @@ +# Memory Extraction Subagent Prompt + +Use this template when dispatching a memory-extraction subagent. + +## Dispatch Template + +``` +Task tool or sub-agent-explore: + name: memory-extract-{timestamp} + instruction: | + You are a memory extraction specialist for this project. + + ## Recent Context + + [Paste recent conversation excerpt - last 5-10 exchanges] + + ## Your Job + + Extract valuable information from the conversation and store it appropriately. + + ### Step 1: Identify Extractable Information + + Look for: + - **Technical decisions**: "decide/choose/use X instead of Y" or "决定/选择/采用/使用" + - **Configuration changes**: env vars, config files, paths + - **User preferences**: "I prefer/like/always use" or "我喜欢/偏好/习惯" + - **Project milestones**: "completed/deployed/released" or "完成/上线/发布" + - **Architecture patterns**: design decisions, patterns adopted + - **Progress updates**: tasks completed, blockers resolved + + ### Step 2: Classify Each Item + + | Scope | Signal | Storage | + |-------|--------|---------| + | PROJECT | Project-specific config, decisions | `_omp/memory/` | + | PERSONAL | User preferences, habits | `openmemory` MCP | + | EPHEMERAL | Temporary, uncertain | Skip | + + ### Step 3: Validate (ROT Filter) + + Skip if: + - ❌ **Trivial**: < 10 chars or simple acknowledgments ("OK/got it/好的/明白了") + - ❌ **Redundant**: Already exists (similarity > 0.85) + - ❌ **Obsolete**: Contradicted by newer info + - ❌ **Sensitive**: API keys, passwords, tokens + + ### Step 4: Store + + **For PROJECT scope** - Update appropriate file: + - Decisions → `_omp/memory/decisions.yaml` + - Config → `_omp/memory/project.yaml` + - Progress → `_omp/memory/progress.md` + - Patterns → `_omp/memory/systemPatterns.md` + - Context → `_omp/memory/activeContext.md` + + **For PERSONAL scope** - Use MCP: + ``` + Tool: add_memories_openmemory + Parameter: text = "[SCOPE:PERSONAL] {extracted info}" + ``` + + ### Step 5: Report + + Format your report as: + ``` + ## Memory Extraction Report + + **Extracted**: N items + **Stored**: + - [PROJECT] decisions.yaml: "Tech decision: TypeScript" + - [PERSONAL] openmemory: "User prefers 2-space indent" + + **Skipped**: M items (reason: trivial/redundant/sensitive) + **Conflicts**: None / [list if any] + ``` +``` + +## Quick Reference + +### Trigger → Storage Mapping + +| Trigger | Target File | Format | +|---------|-------------|--------| +| Task complete | `progress.md` | Markdown list | +| Tech decision | `decisions.yaml` | YAML entry | +| Config change | `project.yaml` | YAML update | +| Deploy status | `project.yaml` | deployment section | +| User preference | `openmemory` | MCP call | +| Architecture | `systemPatterns.md` | Markdown section | +| Session checkpoint | `activeContext.md` | Markdown summary | + +### YAML Entry Template + +```yaml +# For decisions.yaml +- id: dec-{date}-{seq} + date: {YYYY-MM-DD} + title: "{decision title}" + context: "{why this decision}" + choice: "{what was chosen}" + alternatives: ["{other options}"] + impact: "{affected areas}" +``` + +### Validation Checklist + +Before storing, verify: +- [ ] Not trivial (meaningful content > 10 chars) +- [ ] Not redundant (check existing memories) +- [ ] Not sensitive (no secrets/keys/passwords) +- [ ] Confidence >= 0.4 +- [ ] Clear scope (PROJECT or PERSONAL) + +## Example Extraction + +**Input conversation**: +``` +User: I decided to use pnpm instead of npm because it's faster +Agent: OK, updated package manager configuration +``` + +**Extraction**: +```yaml +# → _omp/memory/decisions.yaml +- id: dec-2026-02-03-001 + date: 2026-02-03 + title: "Package Manager Selection" + context: "Performance optimization" + choice: "pnpm" + alternatives: ["npm", "yarn"] + impact: "All npm commands → pnpm" +``` + +**Report**: +``` +## Memory Extraction Report + +**Extracted**: 1 item +**Stored**: +- [PROJECT] decisions.yaml: "Package Manager: pnpm over npm" + +**Skipped**: 0 items +**Conflicts**: None +``` + diff --git a/cli/templates/shared/_omp/skills/memory-extraction/triggers.md b/cli/templates/shared/_omp/skills/memory-extraction/triggers.md new file mode 100644 index 0000000..c0e19c7 --- /dev/null +++ b/cli/templates/shared/_omp/skills/memory-extraction/triggers.md @@ -0,0 +1,177 @@ +# Memory Extraction Triggers + +Defines when to automatically dispatch memory-extraction subagent. + +--- + +## Trigger Priority Levels + +| Priority | Response Time | Description | +|----------|---------------|-------------| +| P0 | Immediate | Critical information, extract now | +| P1 | Soon | Important, extract within 2-3 exchanges | +| P2 | Deferred | Can wait for checkpoint | +| P3 | Checkpoint | Batch with periodic extraction | + +--- + +## Trigger Definitions + +### P0: Immediate Triggers + +#### Task Completion +```yaml +trigger: task_complete +signals: + - Task marked complete in task management + - "✓" or "[x]" in task list + - EN: "done/finished/completed" + task reference + - ZH: "完成/搞定/做好了" + task reference +action: Extract progress update +target: _omp/memory/progress.md +``` + +#### Technical Decision +```yaml +trigger: tech_decision +signals: + - EN: "decide/choose/use X instead of Y" + - ZH: "决定/选择/采用/使用 X 而不是 Y" + - EN: "we'll use/going with" + - Explicit choice between alternatives +action: Record decision with context +target: _omp/memory/decisions.yaml +``` + +### P1: Soon Triggers + +#### Configuration Change +```yaml +trigger: config_change +signals: + - .env file modified + - config.* file modified + - Environment variable set/changed + - EN: "configure/set/update" + value + - ZH: "配置/设置" + value +action: Update project config +target: _omp/memory/project.yaml +``` + +#### Deployment Status +```yaml +trigger: deployment +signals: + - "deploy/vercel/wrangler" command output + - URL change detected + - EN: "deployed/live/published" + - ZH: "上线/发布/部署完成" +action: Update deployment info +target: _omp/memory/project.yaml (deployment section) +``` + +### P2: Deferred Triggers + +#### User Preference +```yaml +trigger: user_preference +signals: + - EN: "I prefer/like/always use/my habit" + - ZH: "我喜欢/偏好/习惯/总是用" + - Repeated behavior pattern (3+ times) +action: Store user preference +target: openmemory MCP +``` + +#### Architecture Pattern +```yaml +trigger: architecture +signals: + - EN: "pattern/architecture/design/structure" + - ZH: "模式/架构/设计/结构" + - Design decision discussion +action: Document pattern +target: _omp/memory/systemPatterns.md +``` + +### P3: Checkpoint Triggers + +#### Periodic Checkpoint +```yaml +trigger: checkpoint +signals: + - Every 10 conversation exchanges + - Session duration > 30 minutes + - Before long operation (build, deploy) +action: Summarize recent context +target: _omp/memory/activeContext.md +``` + +#### Session End +```yaml +trigger: session_end +signals: + - EN: "bye/exit/done for now/thanks" + - ZH: "结束/退出/谢谢/再见" + - User closes conversation + - Inactivity > 5 minutes +action: Full extraction sweep +target: Multiple files + session record +``` + +--- + +## Detection Patterns + +### Chinese Signals (ZH) +```regex +决定|选择|采用|使用|配置|部署|上线 +我喜欢|偏好|习惯|总是用 +完成|搞定|做好了|OK了 +``` + +### English Signals (EN) +```regex +decide|choose|adopt|use|configure|deploy|live +I prefer|like|always use|my habit +done|finished|completed|ready +``` + +### Code Signals (Universal) +```regex +\.env|config\.|settings\.|\.yaml|\.json +deploy|vercel|wrangler|npm run|pnpm +\[x\]|✓|✅|DONE|COMPLETE +``` + +--- + +## Trigger Response Flow + +``` +Event Detected + ↓ +Match Trigger Pattern (EN or ZH) + ↓ +Determine Priority + ↓ +P0/P1: Dispatch subagent immediately +P2: Queue for next checkpoint +P3: Batch with checkpoint + ↓ +Subagent extracts & stores + ↓ +Report back to main agent +``` + +--- + +## Skip Conditions + +Do NOT trigger extraction for: +- Read-only operations (viewing files) +- Temporary/exploratory discussions +- Questions without decisions +- Trivial acknowledgments (EN: "OK/got it", ZH: "好的/明白了") +- Already extracted information + diff --git a/cli/tests/install.test.ts b/cli/tests/install.test.ts index ad3ab32..6e14405 100644 --- a/cli/tests/install.test.ts +++ b/cli/tests/install.test.ts @@ -181,5 +181,95 @@ describe('install command', () => { expect(existsSync(join(TEST_DIR, '_omp', 'patches', 'categorization.py'))).toBe(true); }); }); + + // Issue #6 Fix: Add tests for entry file generation + describe('entry file generation', () => { + it('should create AGENTS.md for augment IDE', () => { + execSync(`node ${CLI_PATH} install -i augment -y --skip-deps`, { + cwd: TEST_DIR, + stdio: 'pipe', + }); + + expect(existsSync(join(TEST_DIR, 'AGENTS.md'))).toBe(true); + + const content = readFileSync(join(TEST_DIR, 'AGENTS.md'), 'utf-8'); + expect(content).toContain('OpenMemory Plus'); + expect(content).toContain('Memory System'); + expect(content).toContain('Session Lifecycle'); + }); + + it('should create CLAUDE.md for claude IDE', () => { + execSync(`node ${CLI_PATH} install -i claude -y --skip-deps`, { + cwd: TEST_DIR, + stdio: 'pipe', + }); + + expect(existsSync(join(TEST_DIR, 'CLAUDE.md'))).toBe(true); + + const content = readFileSync(join(TEST_DIR, 'CLAUDE.md'), 'utf-8'); + expect(content).toContain('OpenMemory Plus'); + expect(content).toContain('Memory System'); + }); + + it('should create .cursor/rules/openmemory.mdc for cursor IDE', () => { + execSync(`node ${CLI_PATH} install -i cursor -y --skip-deps`, { + cwd: TEST_DIR, + stdio: 'pipe', + }); + + expect(existsSync(join(TEST_DIR, '.cursor', 'rules', 'openmemory.mdc'))).toBe(true); + + const content = readFileSync(join(TEST_DIR, '.cursor', 'rules', 'openmemory.mdc'), 'utf-8'); + expect(content).toContain('OpenMemory Plus'); + expect(content).toContain('_omp/memory'); + }); + + it('should create both AGENTS.md and CLAUDE.md for multi-IDE install', () => { + execSync(`node ${CLI_PATH} install -i augment,claude -y --skip-deps`, { + cwd: TEST_DIR, + stdio: 'pipe', + }); + + expect(existsSync(join(TEST_DIR, 'AGENTS.md'))).toBe(true); + expect(existsSync(join(TEST_DIR, 'CLAUDE.md'))).toBe(true); + }); + + it('should include decisions.yaml in memory directory', () => { + execSync(`node ${CLI_PATH} install -i augment -y --skip-deps`, { + cwd: TEST_DIR, + stdio: 'pipe', + }); + + expect(existsSync(join(TEST_DIR, '_omp', 'memory', 'decisions.yaml'))).toBe(true); + + const content = readFileSync(join(TEST_DIR, '_omp', 'memory', 'decisions.yaml'), 'utf-8'); + expect(content).toContain('Technical Decisions Log'); + expect(content).toContain('decisions:'); + }); + + it('should include memory-extraction skill files', () => { + execSync(`node ${CLI_PATH} install -i augment -y --skip-deps`, { + cwd: TEST_DIR, + stdio: 'pipe', + }); + + // Check subagent-prompt.md + expect(existsSync(join(TEST_DIR, '_omp', 'skills', 'memory-extraction', 'subagent-prompt.md'))).toBe(true); + const subagentContent = readFileSync( + join(TEST_DIR, '_omp', 'skills', 'memory-extraction', 'subagent-prompt.md'), + 'utf-8' + ); + expect(subagentContent).toContain('Memory Extraction Subagent'); + expect(subagentContent).toContain('this project'); // Not {{PROJECT_NAME}} + + // Check triggers.md + expect(existsSync(join(TEST_DIR, '_omp', 'skills', 'memory-extraction', 'triggers.md'))).toBe(true); + const triggersContent = readFileSync( + join(TEST_DIR, '_omp', 'skills', 'memory-extraction', 'triggers.md'), + 'utf-8' + ); + expect(triggersContent).toContain('Trigger Priority Levels'); + }); + }); });