4df9f61347
* fix: stop generating empty CLAUDE.md files - Return empty string instead of "No recent activity" when no observations exist - Skip writing CLAUDE.md files when formatted content is empty - Remove redundant "auto-generated by claude-mem" HTML comment - Clean up 98 existing empty CLAUDE.md files across the codebase - Update tests to expect empty string for empty input Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * build assets * refactor: implement in-process worker architecture for hooks Replaces spawn-based worker startup with in-process architecture: - Hook processes now become the worker when port 37777 is free - Eliminates Windows spawn issues (NO SPAWN rule) - SessionStart chains: smart-install && stop && context Key changes: - worker-service.ts: hook case starts WorkerService in-process - hook-command.ts: skipExit option prevents process.exit() when hosting worker - hooks.json: single chained command replaces separate start/hook commands - worker-utils.ts: ensureWorkerRunning() returns boolean, doesn't block - handlers: graceful fallback when worker unavailable All 761 tests pass. Manual verification confirms hook stays alive as worker. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * context * a * MAESTRO: Mark PR #722 test verification task complete All 797 tests passed (3 skipped, 0 failed) after merge conflict resolution. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * MAESTRO: Mark PR #722 build verification task complete * MAESTRO: Mark PR #722 code review task complete Code review verified: - worker-service.ts hook case starts WorkerService in-process - hook-command.ts has skipExit option - hooks.json uses single chained command - worker-utils.ts ensureWorkerRunning() returns boolean Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * MAESTRO: Mark PR #722 conflict resolution push task complete Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
267 lines
8.2 KiB
Markdown
267 lines
8.2 KiB
Markdown
# Plan: Fix Empty CLAUDE.md File Generation
|
|
|
|
## Problem Statement
|
|
|
|
Currently the CLAUDE.md generator creates files with wasteful content:
|
|
1. **Empty files with "No recent activity"** - Files are created even when there are zero observations for a folder
|
|
2. **Redundant HTML comment** - "<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->" is unnecessary since the `<claude-mem-context>` tag already conveys this information
|
|
|
|
These issues create noisy, wasteful context that loads automatically and provides no value.
|
|
|
|
## Phase 0: Documentation Discovery
|
|
|
|
### Allowed APIs (from code analysis)
|
|
- `formatTimelineForClaudeMd(timelineText: string): string` - src/utils/claude-md-utils.ts:139
|
|
- `formatObservationsForClaudeMd(observations, folderPath): string` - scripts/regenerate-claude-md.ts:238
|
|
- `writeClaudeMdToFolder(folderPath, newContent): void` - src/utils/claude-md-utils.ts:94
|
|
- `updateFolderClaudeMdFiles(filePaths, project, port, projectRoot): Promise<void>` - src/utils/claude-md-utils.ts:257
|
|
- `replaceTaggedContent(existingContent, newContent): string` - src/utils/claude-md-utils.ts:64
|
|
|
|
### Key Locations
|
|
| File | Lines | Purpose |
|
|
|------|-------|---------|
|
|
| `src/utils/claude-md-utils.ts` | 139-235 | Main formatting function |
|
|
| `src/utils/claude-md-utils.ts` | 143 | HTML comment generation |
|
|
| `src/utils/claude-md-utils.ts` | 209-211 | "No recent activity" handling |
|
|
| `src/utils/claude-md-utils.ts` | 322-323 | Write decision point |
|
|
| `scripts/regenerate-claude-md.ts` | 238-286 | Regeneration script formatting |
|
|
| `scripts/regenerate-claude-md.ts` | 242 | HTML comment generation (duplicate) |
|
|
| `scripts/regenerate-claude-md.ts` | 245-247 | "No recent activity" handling |
|
|
| `scripts/regenerate-claude-md.ts` | 452-453 | Write decision point |
|
|
| `tests/utils/claude-md-utils.test.ts` | 96-109 | Tests for "No recent activity" behavior |
|
|
|
|
### Anti-patterns to avoid
|
|
- Do NOT add new configuration options for this behavior - just fix it
|
|
- Do NOT add logging for skipped files (unnecessary noise)
|
|
|
|
---
|
|
|
|
## Phase 1: Modify formatTimelineForClaudeMd to Return Empty on No Observations
|
|
|
|
### Task 1.1: Update formatTimelineForClaudeMd return behavior
|
|
**File:** `src/utils/claude-md-utils.ts`
|
|
**Lines:** 139-235
|
|
|
|
**Changes:**
|
|
1. Remove HTML comment line at line 143
|
|
2. Change the empty observations case (lines 209-211) to return an empty string instead of "No recent activity"
|
|
|
|
**Before (lines 141-144):**
|
|
```typescript
|
|
lines.push('# Recent Activity');
|
|
lines.push('');
|
|
lines.push('<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->');
|
|
lines.push('');
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
lines.push('# Recent Activity');
|
|
lines.push('');
|
|
```
|
|
|
|
**Before (lines 209-212):**
|
|
```typescript
|
|
if (observations.length === 0) {
|
|
lines.push('*No recent activity*');
|
|
return lines.join('\n');
|
|
}
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
if (observations.length === 0) {
|
|
return '';
|
|
}
|
|
```
|
|
|
|
### Verification
|
|
- Run `bun test tests/utils/claude-md-utils.test.ts`
|
|
- Tests at lines 96-109 will FAIL (expected - they test for "No recent activity")
|
|
- Update tests to expect empty string for empty input
|
|
|
|
---
|
|
|
|
## Phase 2: Update updateFolderClaudeMdFiles to Skip Empty Content
|
|
|
|
### Task 2.1: Add empty content check before writing
|
|
**File:** `src/utils/claude-md-utils.ts`
|
|
**Lines:** 322-323
|
|
|
|
**Changes:**
|
|
After formatting, check if result is empty and skip writing if so.
|
|
|
|
**Before (lines 321-325):**
|
|
```typescript
|
|
const formatted = formatTimelineForClaudeMd(result.content[0].text);
|
|
writeClaudeMdToFolder(folderPath, formatted);
|
|
|
|
logger.debug('FOLDER_INDEX', 'Updated CLAUDE.md', { folderPath });
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
const formatted = formatTimelineForClaudeMd(result.content[0].text);
|
|
if (!formatted) {
|
|
logger.debug('FOLDER_INDEX', 'No observations for folder, skipping', { folderPath });
|
|
continue;
|
|
}
|
|
writeClaudeMdToFolder(folderPath, formatted);
|
|
|
|
logger.debug('FOLDER_INDEX', 'Updated CLAUDE.md', { folderPath });
|
|
```
|
|
|
|
### Verification
|
|
- Grep for files containing "No recent activity": should find none after running
|
|
|
|
---
|
|
|
|
## Phase 3: Update Regeneration Script
|
|
|
|
### Task 3.1: Remove HTML comment from formatObservationsForClaudeMd
|
|
**File:** `scripts/regenerate-claude-md.ts`
|
|
**Lines:** 238-286
|
|
|
|
**Changes:**
|
|
1. Remove HTML comment line at line 242
|
|
2. Change empty observations case (lines 245-247) to return empty string
|
|
|
|
**Before (lines 240-244):**
|
|
```typescript
|
|
lines.push('# Recent Activity');
|
|
lines.push('');
|
|
lines.push('<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->');
|
|
lines.push('');
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
lines.push('# Recent Activity');
|
|
lines.push('');
|
|
```
|
|
|
|
**Before (lines 245-248):**
|
|
```typescript
|
|
if (observations.length === 0) {
|
|
lines.push('*No recent activity*');
|
|
return lines.join('\n');
|
|
}
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
if (observations.length === 0) {
|
|
return '';
|
|
}
|
|
```
|
|
|
|
### Task 3.2: Update regenerateFolder to handle empty formatted content
|
|
**File:** `scripts/regenerate-claude-md.ts`
|
|
**Lines:** 432-459
|
|
|
|
The script already skips folders with no observations (lines 443-444), so this change is already compatible. The `formatObservationsForClaudeMd` returning empty string doesn't change behavior since observations are checked before calling it.
|
|
|
|
### Verification
|
|
- Run `bun scripts/regenerate-claude-md.ts --dry-run` in the project
|
|
- Should NOT show any folders with 0 observations
|
|
|
|
---
|
|
|
|
## Phase 4: Update Tests
|
|
|
|
### Task 4.1: Update tests for new empty behavior
|
|
**File:** `tests/utils/claude-md-utils.test.ts`
|
|
**Lines:** 96-109
|
|
|
|
**Changes:**
|
|
Update the two tests that expect "No recent activity" to expect empty string instead.
|
|
|
|
**Before (lines 96-101):**
|
|
```typescript
|
|
it('should return "No recent activity" for empty input', () => {
|
|
const result = formatTimelineForClaudeMd('');
|
|
|
|
expect(result).toContain('# Recent Activity');
|
|
expect(result).toContain('*No recent activity*');
|
|
});
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
it('should return empty string for empty input', () => {
|
|
const result = formatTimelineForClaudeMd('');
|
|
|
|
expect(result).toBe('');
|
|
});
|
|
```
|
|
|
|
**Before (lines 103-109):**
|
|
```typescript
|
|
it('should return "No recent activity" when no table rows exist', () => {
|
|
const input = 'Just some plain text without table rows';
|
|
|
|
const result = formatTimelineForClaudeMd(input);
|
|
|
|
expect(result).toContain('*No recent activity*');
|
|
});
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
it('should return empty string when no table rows exist', () => {
|
|
const input = 'Just some plain text without table rows';
|
|
|
|
const result = formatTimelineForClaudeMd(input);
|
|
|
|
expect(result).toBe('');
|
|
});
|
|
```
|
|
|
|
### Task 4.2: Remove HTML comment assertions from any other tests
|
|
Search for tests that assert on "auto-generated" comment and update accordingly.
|
|
|
|
### Verification
|
|
- Run full test suite: `bun test`
|
|
- All tests should pass
|
|
|
|
---
|
|
|
|
## Phase 5: Cleanup Existing Empty Files
|
|
|
|
### Task 5.1: Run cleanup to remove existing empty CLAUDE.md files
|
|
**Command:**
|
|
```bash
|
|
bun scripts/regenerate-claude-md.ts --clean
|
|
```
|
|
|
|
This will:
|
|
- Find all CLAUDE.md files with `<claude-mem-context>` tags
|
|
- Strip the tagged section
|
|
- Delete files that become empty after stripping
|
|
- Preserve files that have user content outside the tags
|
|
|
|
### Verification
|
|
- `grep -r "No recent activity" . --include="CLAUDE.md"` should return no results
|
|
- `grep -r "auto-generated by claude-mem" . --include="CLAUDE.md"` should return no results
|
|
|
|
---
|
|
|
|
## Summary of Changes
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `src/utils/claude-md-utils.ts:143` | Remove HTML comment line |
|
|
| `src/utils/claude-md-utils.ts:209-211` | Return empty string instead of "No recent activity" |
|
|
| `src/utils/claude-md-utils.ts:322` | Skip writing if formatted content is empty |
|
|
| `scripts/regenerate-claude-md.ts:242` | Remove HTML comment line |
|
|
| `scripts/regenerate-claude-md.ts:245-247` | Return empty string instead of "No recent activity" |
|
|
| `tests/utils/claude-md-utils.test.ts:96-109` | Update tests to expect empty string |
|
|
|
|
## Final Verification Checklist
|
|
- [ ] `bun test` passes
|
|
- [ ] No "No recent activity" CLAUDE.md files exist
|
|
- [ ] No "auto-generated" comments in CLAUDE.md files
|
|
- [ ] Build succeeds: `npm run build-and-sync`
|
|
- [ ] New observations correctly generate CLAUDE.md files with content
|
|
- [ ] Folders without observations get no CLAUDE.md file created
|