Commit Graph

11 Commits

Author SHA1 Message Date
Tom Cruise Missile
6a40469408 feat: Cursor-independent ECC memory via ECC_AGENT_DATA_HOME (#2066)
* feat: auto-isolate ECC memory data for Cursor via ECC_AGENT_DATA_HOME

Add ECC_AGENT_DATA_HOME (defaults to ~/.claude) with Cursor-aware resolution,
sessionStart env injection, install scaffolds, and hook bootstrap so memory
hooks do not collide with Claude Code when both harnesses are used.

Closes #2065

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: log agent-data config errors and ship cursor sessionStart deps

Address CodeRabbit review: log invalid .cursor/ecc-agent-data.json parse
failures, and copy cursor-session-env.js plus lib deps on legacy Cursor
install so sessionStart hook path exists without hooks-runtime alone.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: resolve relative agentDataHome paths from project root

Project config values like ".ecc-data" now resolve against the
repository root (parent of .cursor/), not process.cwd(), so Cursor
hooks persist memory in the intended directory regardless of hook cwd.

Addresses cubic review on PR #2066.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: explain getHomeDir duplicate and docstring policy

Document why agent-data-home keeps a local home-dir helper (circular
require with utils.js) and list consolidation options for maintainers.
Note that CodeRabbit JSDoc coverage warnings are informational relative
to ECC's usual script documentation style.

Addresses cubic P2 context on PR #2066.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: isolate agent-data-home tests from dogfooded .cursor config

Use isolated temp cwd for default-resolution cases and assert
resolveAgentDataHome({ projectDir }) reads ecc-agent-data.json.
Document cwd/project caveats in the test file header.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-07 13:27:00 +08:00
Affaan Mustafa
dc11fc2fd8 fix: make saveAliases atomic on Unix by skipping unnecessary unlink before rename
On Unix/macOS, rename(2) atomically replaces the destination file.
The previous code ran unlinkSync before renameSync on all platforms,
creating an unnecessary non-atomic window where a crash could lose
data. Now the delete-before-rename is gated behind process.platform
=== 'win32', where rename cannot overwrite an existing file.
2026-02-13 04:23:22 -08:00
Affaan Mustafa
f33ed4c49e fix: clamp getAllSessions pagination params, add cleanupAliases success field, add 10 tests
- session-manager: clamp offset/limit to safe non-negative integers to
  prevent negative offset counting from end and NaN returning empty results
- session-aliases: add success field to cleanupAliases return value for
  API contract consistency with setAlias/deleteAlias/renameAlias
2026-02-13 02:16:22 -08:00
Affaan Mustafa
654731f232 fix: add missing validation in renameAlias, add 6 tests
renameAlias was missing length (>128), reserved name, and empty string
validation that setAlias enforced. This inconsistency allowed renaming
aliases to reserved names like 'list' or 'delete'.

Also adds tests for:
- renameAlias empty string, reserved name, and length limit
- validate-skills whitespace-only SKILL.md rejection
- validate-rules whitespace-only file and recursive subdirectory scan
2026-02-13 01:05:59 -08:00
Affaan Mustafa
76b271ab6b fix: 6 bugs fixed, 67 tests added for session-manager and session-aliases
Bug fixes:
- utils.js: prevent duplicate 'g' flag in countInFile regex construction
- validate-agents.js: handle CRLF line endings in frontmatter parsing
- validate-hooks.js: handle \t and \\ escape sequences in inline JS validation
- session-aliases.js: prevent NaN in date sort when timestamps are missing
- session-aliases.js: persist rollback on rename failure instead of silent loss
- session-manager.js: require absolute paths in getSessionStats to prevent
  content strings ending with .tmp from being treated as file paths

New tests (164 total, up from 97):
- session-manager.test.js: 27 tests covering parseSessionFilename,
  parseSessionMetadata, getSessionStats, CRUD operations, getSessionSize,
  getSessionTitle, edge cases (null input, non-existent files, directories)
- session-aliases.test.js: 40 tests covering loadAliases (corrupted JSON,
  invalid structure), setAlias (validation, reserved names), resolveAlias,
  listAliases (sort, search, limit), deleteAlias, renameAlias, updateAliasTitle,
  resolveSessionAlias, getAliasesForSession, cleanupAliases, atomic write

Also includes hook-generated improvements:
- utils.d.ts: document that readStdinJson never rejects
- session-aliases.d.ts: fix updateAliasTitle type to accept null
- package-manager.js: add try-catch to setProjectPackageManager writeFile
2026-02-12 15:50:04 -08:00
Affaan Mustafa
9e791ed305 fix: harden utils.js edge cases and add input validation
- Guard findFiles() against null/undefined dir and pattern parameters
  (previously crashed with TypeError on .replace() or fs.existsSync())
- Wrap countInFile() and grepFile() regex construction in try-catch to
  handle invalid regex strings like '(unclosed' (previously crashed with
  SyntaxError: Invalid regular expression)
- Add try-catch to replaceInFile() with descriptive error logging
- Add 1MB size limit to readStdinJson() matching the PostToolUse hooks
  (previously had unbounded stdin accumulation)
- Improve ensureDir() error message to include the directory path
- Add 128-char length limit to setAlias() to prevent oversized alias
  names from inflating the JSON store
- Update utils.d.ts with new maxSize option on ReadStdinJsonOptions
2026-02-12 14:49:11 -08:00
Affaan Mustafa
63be081741 fix: renameAlias data corruption, empty sessionId match, NaN threshold
- Fix renameAlias() leaving orphaned newAlias key on save failure,
  causing in-memory data corruption with both old and new keys present
- Add sessionPath validation to setAlias() to reject empty/null paths
- Guard getSessionById() against empty string matching all sessions
  (startsWith('') is always true in JavaScript)
- Fix suggest-compact.js NaN comparison when COMPACT_THRESHOLD env var
  is set to a non-numeric value — falls back to 50 instead of silently
  disabling the threshold check
- Sync suggest-compact.js to .cursor/ copy
2026-02-12 14:30:10 -08:00
Affaan Mustafa
7e852a5dc5 fix: remove dead export, harden session-aliases, sync .cursor scripts
- Remove duplicate getAliasesPath() from utils.js (only used in
  session-aliases.js which has its own copy)
- session-aliases.js: validate cleanupAliases param is a function,
  check saveAliases return value, guard resolveAlias against empty input
- Sync .cursor/skills/strategic-compact/suggest-compact.sh with the
  fixed main version (CLAUDE_SESSION_ID instead of $$)
2026-02-12 13:43:53 -08:00
Affaan Mustafa
18c5a76a96 fix: improve error handling, fix bugs, and optimize core libraries
utils.js:
- Fix countInFile: enforce global flag on regex to prevent silent
  under-counting (match() without /g returns only first match)
- Add 5s timeout to readStdinJson to prevent hooks hanging forever
- Handle EEXIST race condition in ensureDir
- Pre-compile regex patterns in getGitModifiedFiles to avoid N*M
  compilations and catch invalid patterns before filtering
- Add JSDoc documentation to all improved functions

session-manager.js:
- Fix getSessionById triple file read: pass pre-read content to
  getSessionStats instead of re-reading from disk
- Allow getSessionStats to accept content string directly

session-aliases.js:
- Wrap temp file cleanup in try/catch to prevent cascading errors

check-console-log.js:
- Refactor to use shared utils (isGitRepo, getGitModifiedFiles, log)
  instead of raw execSync calls
- Add exclusion patterns for test files, config files, and scripts/
  where console.log is intentional

session-end.js:
- Log count of skipped unparseable transcript lines for diagnostics

suggest-compact.js:
- Guard against NaN from corrupted counter files

package-manager.js:
- Remove dead fallbackOrder parameter (unused after #162 fix)
2026-02-12 07:06:53 -08:00
ericcai
d2191d09a2 fix: sync plugin.json version with latest tag (#171)
Sync plugin.json version to 1.4.1, add CI check to verify versions match on release, and add release.sh script. Fixes #170.
2026-02-08 16:18:49 -08:00
xcfdszzr
d85b1ae52e feat: add /sessions command for session history management (#142)
Add a new /sessions command to manage Claude Code session history with
alias support for quick access to previous sessions.

Features:
- List sessions with pagination and filtering (by date, ID)
- Load and view session content and metadata
- Create memorable aliases for sessions
- Remove aliases
- Display session statistics (lines, items, size)
- List all aliases

New libraries:
- scripts/lib/session-manager.js - Core session CRUD operations
- scripts/lib/session-aliases.js - Alias management with atomic saves

New command:
- commands/sessions.md - Complete command with embedded scripts

Modified:
- scripts/lib/utils.js - Add getAliasesPath() export
- scripts/hooks/session-start.js - Show available aliases on session start

Session format support:
- Old: YYYY-MM-DD-session.tmp
- New: YYYY-MM-DD-<short-id>-session.tmp

Aliases are stored in ~/.claude/session-aliases.json with Windows-
compatible atomic writes and backup support.

Co-authored-by: 王志坚 <wangzhijian10@bgyfw.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-02-02 16:51:37 -08:00