Commit Graph

37 Commits

Author SHA1 Message Date
Affaan Mustafa
926eba97c5 fix: add input validation, date range checks, and security hardening
- validate-agents.js: reject invalid model names in agent frontmatter
- package-manager.js: validate script/binary names against shell injection
- session-manager.js: reject impossible month/day values in filenames
- utils.js: support options.all for replaceInFile string patterns
- strategic-compact/SKILL.md: fix hook matcher syntax and script reference
- install.sh: warn when overwriting existing rule customizations
- Add 24 new tests covering all validation and edge cases
2026-02-12 17:32:04 -08:00
Affaan Mustafa
5107b3669f fix: box() off-by-one alignment, add 5 tests for readStdinJson and box alignment
- skill-create-output.js: fix top border being 1 char narrower than
  middle/bottom lines (width - title - 5 → width - title - 4)
- Add box alignment regression test verifying all lines have equal width
- Add 4 readStdinJson tests via subprocess (valid JSON, invalid JSON,
  empty stdin, nested objects) — last untested exported utility function
- All 338 tests passing
2026-02-12 16:53:06 -08:00
Affaan Mustafa
924bac4ddf fix: add word boundary to dev server hook regex, fix box() crash, add 27 tests
- hooks.json: add \b word boundary anchors to dev server blocking regex
  to prevent false positives matching "npm run develop", "npm run devtools" etc.
- skill-create-output.js: guard box() horizontal repeat with Math.max(0, ...)
  to prevent RangeError when title exceeds container width
- Add 13 tests for setup-package-manager.js CLI argument parsing
- Add 14 tests for skill-create-output.js SkillCreateOutput class
- All 333 tests passing
2026-02-12 16:46:06 -08:00
Affaan Mustafa
b1b28f2f92 fix: capture stderr in typecheck hook, add 13 tests for session-end and utils
- post-edit-typecheck.js: capture both stdout and stderr from tsc
- hooks.test.js: 7 extractSessionSummary tests (JSONL parsing, array content,
  malformed lines, empty transcript, long message truncation, env var fallback)
- utils.test.js: 6 tests (replaceInFile g-flag behavior, string replace,
  capture groups, writeFile overwrite, unicode content)

Total test count: 294 → 307
2026-02-12 16:31:07 -08:00
Affaan Mustafa
7ec5fc3a52 fix: add event type enum to hooks schema and avoid shared RegExp state
- hooks.schema.json: add enum constraint for hook event types
  (PreToolUse, PostToolUse, PreCompact, SessionStart, SessionEnd,
  Stop, Notification, SubagentStop) — enables IDE autocompletion
  and compile-time validation
- utils.js countInFile: always create fresh RegExp to avoid shared
  lastIndex state when reusing global regex instances
- README: update AgentShield stats (751 tests, 73 rules)
2026-02-12 16:24:48 -08:00
Affaan Mustafa
bc0520c6c1 fix: broken cross-references, version sync, and enhanced command validator
- Fix /build-and-fix → /build-fix in tdd.md, plan.md (+ cursor, zh-CN)
- Fix non-existent explorer agent → planner in orchestrate.md (+ cursor, zh-CN, zh-TW)
- Fix /python-test → /tdd in python-review.md (+ cursor, zh-CN)
- Sync package.json version from 1.0.0 to 1.4.1 to match plugin.json
- Enhance validate-commands.js with cross-reference checking:
  command refs, agent path refs, skill dir refs, workflow diagrams
- Strip fenced code blocks before scanning to avoid false positives
- Skip hypothetical "Creates:" lines in evolve.md examples
- Add 46 new tests (suggest-compact, session-manager, utils, hooks)
2026-02-12 16:19:04 -08:00
Affaan Mustafa
8ff54d8b06 fix: skip code blocks in command cross-reference validation
The validator was matching example/template content inside fenced code
blocks as real cross-references, causing false positives for evolve.md
(example /new-table command and debugger agent).

- Strip ``` blocks before running cross-reference checks
- Change evolve.md examples to use bold instead of backtick formatting
  for hypothetical outputs

All 261 tests pass.
2026-02-12 16:18:50 -08:00
Affaan Mustafa
492c99ac24 fix: 3 bugs fixed, stdin encoding hardened, 37 CI validator tests added
Bug fixes:
- utils.js: glob-to-regex conversion now escapes all regex special chars
  (+, ^, $, |, (), {}, [], \) before converting * and ? wildcards
- validate-hooks.js: escape sequence processing order corrected —
  \\\\ now processed before \\n and \\t to prevent double-processing
- 6 hooks: added process.stdin.setEncoding('utf8') to prevent
  multi-byte UTF-8 character corruption at chunk boundaries
  (check-console-log, post-edit-format, post-edit-typecheck,
  post-edit-console-warn, session-end, evaluate-session)

New tests (37):
- CI validator test suite (tests/ci/validators.test.js):
  - validate-agents: 9 tests (real project, frontmatter parsing,
    BOM/CRLF, colons in values, missing fields, non-md skip)
  - validate-hooks: 13 tests (real project, invalid JSON, invalid
    event types, missing fields, async/timeout validation, inline JS
    syntax, array commands, legacy format)
  - validate-skills: 6 tests (real project, missing SKILL.md, empty
    files, non-directory entries)
  - validate-commands: 5 tests (real project, empty files, non-md skip)
  - validate-rules: 4 tests (real project, empty files)

Total test count: 228 (up from 191)
2026-02-12 16:08:49 -08:00
Affaan Mustafa
90ea2f327c fix: 2 bugs fixed, 17 tests added for hook scripts
Bug fixes:
- evaluate-session.js: whitespace-tolerant regex for counting user
  messages in JSONL transcripts (/"type":"user"/ → /"type"\s*:\s*"user"/)
- session-end.js: guard against null elements in content arrays
  (c.text → (c && c.text) to prevent TypeError)

New tests (17):
- evaluate-session: whitespace JSON regression test
- session-end: null content array elements regression test
- post-edit-console-warn: 5 tests (warn, skip non-JS, clean files,
  missing file, stdout passthrough)
- post-edit-format: 3 tests (empty stdin, non-JS skip, invalid JSON)
- post-edit-typecheck: 4 tests (empty stdin, non-TS skip, missing file,
  no tsconfig)

Total test count: 191 (up from 164)
2026-02-12 16:02:31 -08:00
Affaan Mustafa
40a4fafa7f fix: add async/timeout to hooks schema and validate in CI
- hooks.schema.json: add async (boolean) and timeout (number) properties
  to hookItem definition, matching fields used in hooks.json
- validate-hooks.js: validate async and timeout types when present
- hooks.test.js: add SessionEnd to required event types check
2026-02-12 15:58:59 -08:00
Affaan Mustafa
639c9aaca3 fix: Windows path support, error handling, and dedup in validators
- session-manager.js: fix getSessionStats path detection to handle
  Windows paths (C:\...) in addition to Unix paths (/)
- package-manager.js: add try-catch to setPreferredPackageManager for
  consistent error handling with setProjectPackageManager
- validate-hooks.js: extract duplicated hook entry validation into
  reusable validateHookEntry() helper
- Update .d.ts JSDoc for both fixes
2026-02-12 15:57:20 -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
ed7ec29ead fix: migrate hooks to stdin JSON input, fix duplicate main() calls, add threshold validation
- Migrate session-end.js and evaluate-session.js from CLAUDE_TRANSCRIPT_PATH
  env var to stdin JSON transcript_path (correct hook input mechanism)
- Remove duplicate main() calls that ran before stdin was read, causing
  session files to be created with empty data
- Add range validation (1-10000) on COMPACT_THRESHOLD in suggest-compact.js
  to prevent negative or absurdly large thresholds
- Add integration/hooks.test.js to tests/run-all.js so CI runs all 97 tests
- Update evaluate-session.sh to parse transcript_path from stdin JSON
- Update hooks.test.js to pass transcript_path via stdin instead of env var
- Sync .cursor/ copies
2026-02-12 15:33:55 -08:00
Affaan Mustafa
3546abc6ea fix: remove unused fs imports in 3 hook scripts
readFile utility replaced direct fs usage but the imports weren't
removed, causing ESLint no-unused-vars failures in CI.
2026-02-12 15:33:51 -08:00
Affaan Mustafa
e7b5c62eb7 fix: use readFile utility in hooks and add pattern type safety
- Replace raw fs.readFileSync with readFile() from utils in
  check-console-log.js and post-edit-console-warn.js to eliminate
  TOCTOU race conditions (file deleted between existsSync and read)
- Remove redundant existsSync in post-edit-format.js (exec already
  handles missing files via its catch block)
- Resolve path upfront in post-edit-typecheck.js before tsconfig walk
- Add type guard in getGitModifiedFiles() to skip non-string and
  empty patterns before regex compilation
2026-02-12 15:28:30 -08:00
Affaan Mustafa
911d38f686 feat: add 3 new skills, JS syntax validation in hooks CI, and edge case tests
- New skills: api-design, database-migrations, deployment-patterns
- validate-hooks.js: validate inline JS syntax in node -e hook commands
- utils.test.js: edge case tests for findFiles with null/undefined inputs
- README: update skill count to 35, add new skills to directory tree
2026-02-12 15:24:28 -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
6686cb9bda fix: add try-catch to inline hooks, fix schema drift
- Wrap JSON.parse in try-catch for all 6 inline hooks in hooks.json
  (dev-server blocker, tmux reminder, git-push reminder, doc blocker,
  PR create logger, build analysis) — previously unguarded JSON.parse
  would crash on empty/malformed stdin, preventing data passthrough
- Add config parse error logging to evaluate-session.js
- Fix plugin.schema.json: author can be string or {name,url} object,
  add version (semver pattern), homepage, keywords, skills, agents
- Fix package-manager.schema.json: add setAt (date-time) field and
  make packageManager required to match actual code behavior
2026-02-12 14:38:00 -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
6e5b45ed28 fix: path traversal in install.sh, error logging in hooks
- Validate language names in install.sh to prevent path traversal via
  malicious args like ../../etc (only allow [a-zA-Z0-9_-])
- Replace silent catch in check-console-log.js with stderr logging so
  hook failures are visible to the user for debugging
- Escape backticks in session-end.js user messages to prevent markdown
  structure corruption in session files
2026-02-12 14:14:21 -08:00
Affaan Mustafa
f3a4b33d41 fix: harden CI validators, shell scripts, and expand test suite
- Add try-catch around readFileSync in validate-agents, validate-commands,
  validate-skills to handle TOCTOU races and file read errors
- Add validate-hooks.js and all test suites to package.json test script
  (was only running 4/5 validators and 0/4 test files)
- Fix shell variable injection in observe.sh: use os.environ instead of
  interpolating $timestamp/$OBSERVATIONS_FILE into Python string literals
- Fix $? always being 0 in start-observer.sh: capture exit code before
  conditional since `if !` inverts the status
- Add OLD_VERSION validation in release.sh and use pipe delimiter in sed
  to avoid issues with slash-containing values
- Add jq dependency check in evaluate-session.sh before parsing config
- Sync .cursor/ copies of all modified shell scripts
2026-02-12 14:11:33 -08:00
Affaan Mustafa
be0ba0cabc feat: add TypeScript declaration files for all core libraries
Add .d.ts type definitions for all four library modules:
- utils.d.ts: Platform detection, file ops, hook I/O, git helpers
- package-manager.d.ts: PM detection with PackageManagerName union type,
  DetectionSource union, and typed config interfaces
- session-manager.d.ts: Session CRUD with Session, SessionMetadata,
  SessionStats, and SessionListResult interfaces
- session-aliases.d.ts: Alias management with typed result interfaces
  for set, delete, rename, and cleanup operations

These provide IDE autocomplete and type-checking for TypeScript
consumers of the npm package without converting the source to TS.
2026-02-12 13:56:48 -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
36864ea11a fix: harden error handling, fix TOCTOU races, and improve test accuracy
Core library fixes:
- session-manager.js: wrap all statSync calls in try-catch to prevent
  TOCTOU crashes when files are deleted between readdir and stat
- session-manager.js: use birthtime||ctime fallback for Linux compat
- session-manager.js: remove redundant existsSync before readFile
- utils.js: fix findFiles TOCTOU race on statSync inside readdir loop

Hook improvements:
- Add 1MB stdin buffer limits to all PostToolUse hooks to prevent
  unbounded memory growth from large payloads
- suggest-compact.js: use fd-based atomic read+write for counter file
  to reduce race window between concurrent invocations
- session-end.js: log when transcript file is missing, check
  replaceInFile return value for failed timestamp updates
- start-observer.sh: log claude CLI failures instead of silently
  swallowing them, check observations file exists before analysis

Test fixes:
- Fix blocking hook tests to send matching input (dev server command)
  and expect correct exit code 2 instead of 1
2026-02-12 13:40:14 -08:00
Affaan Mustafa
7356fd996f refactor: extract inline PostToolUse hooks into external scripts
Move three complex inline hooks from hooks.json into proper external
scripts in scripts/hooks/:

- post-edit-format.js: Prettier auto-formatting (was 1 minified line)
- post-edit-typecheck.js: TypeScript check (was 1 minified line with
  unbounded directory traversal, now capped at 20 levels)
- post-edit-console-warn.js: console.log warnings (was 1 minified line)

Benefits:
- Readable, documented, and properly error-handled
- Testable independently via stdin
- Consistent with other hooks (all use external scripts now)
- Adds timeouts to Prettier (15s) and tsc (30s) to prevent hangs
2026-02-12 10:21:59 -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
Affaan Mustafa
75ab8e6194 fix: eliminate child process spawns during session startup (#162)
getAvailablePackageManagers() spawned where.exe/which for each package
manager (npm, pnpm, yarn, bun). During SessionStart hooks, these 4+
child processes combined with Bun's own initialization exceeded the
spawn limit on Windows, freezing the terminal.

Fix: Remove process spawning from the hot path. Steps 1-5 of detection
(env var, project config, package.json, lock file, global config) already
cover all file-based detection. If none match, default to npm without
spawning. Also fix getSelectionPrompt() to list supported PMs without
checking availability.
2026-02-12 00:01:23 -08:00
Affaan Mustafa
87d19f97a6 fix(sessions): make session hooks actually persist and load context (#187)
session-end.js: Extract meaningful summaries from CLAUDE_TRANSCRIPT_PATH
instead of writing blank template files. Pulls user messages, tools used,
and files modified from the session transcript JSONL.

session-start.js: Output the latest session summary to stdout (via the
output() helper) so it gets injected into Claude's conversation context,
instead of only logging to stderr which just shows briefly in the terminal.
2026-02-11 23:56:41 -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
Affaan Mustafa
a44a0553bb fix: resolve ESLint errors and update tests for project-name fallback
- Fix 16 ESLint no-unused-vars errors across hook scripts and tests
- Add eslint-disable comment for intentional control-regex in ANSI stripper
- Update session file test to use getSessionIdShort() instead of hardcoded 'default'
  (reflects PR #110's project-name fallback behavior)
- Add marketing/ to .gitignore (local drafts)
- Add skill-create-output.js (terminal output formatter)

All 69 tests now pass. CI should be green.
2026-01-29 02:58:51 -08:00
Roei Bar Aviv
7c0bc25982 feat: add comprehensive CI/CD pipeline
Adds GitHub Actions workflows for CI, maintenance, and releases with multi-platform testing matrix.
2026-01-28 23:05:43 -08:00
tchoudhary74
81003b1ca6 feat: use project name as session filename fallback
Fixes #99. Falls back to git repo name or directory name when CLAUDE_SESSION_ID is unavailable.
2026-01-28 23:01:19 -08:00
李成喆
a0b84f7b86 Fix: Move Stop hook inline code to separate script file
Fixes #78

## Problem
The Stop hook used inline JavaScript code with `node -e`, which caused
shell syntax errors on macOS/zsh due to special characters (parentheses,
braces, arrow functions) being misinterpreted by the shell.

Error message:
/bin/sh: -c: line 0: syntax error near unexpected token \`('

## Solution
- Created scripts/hooks/check-console-log.js with the hook logic
- Updated hooks/hooks.json to reference the external script
- This follows the same pattern as other hooks in the plugin

## Benefits
- Fixes shell compatibility issues across different environments
- Improves code maintainability (separate, well-documented script)
- Follows plugin's own best practices
- Makes the code easier to test and debug

## Testing
Tested on macOS with zsh - no more syntax errors.
The hook still functions correctly to detect console.log statements.
2026-01-26 12:00:39 +08:00
Affaan Mustafa
5c63fa9006 feat: v1.1.0 release - session ID tracking, async hooks, new skills
- Add session ID to session filenames (Issue #62)
- Add getSessionIdShort() helper for unique per-session tracking
- Add async hooks documentation with example
- Create iterative-retrieval skill for progressive context refinement
- Add continuous-learning-v2 skill with instinct-based learning
- Add ecc.tools ecosystem section to README
- Update skills list in README

All 67 tests passing.
2026-01-25 18:21:27 -08:00
Affaan Mustafa
660e0d3bad fix: security and documentation fixes
- fix(utils.js): prevent command injection in commandExists() by using
  spawnSync instead of execSync with string interpolation, and validate
  input to only allow alphanumeric chars, dash, underscore, dot (#42)

- fix(utils.js): add security documentation to runCommand() warning
  against passing user-controlled input

- fix(setup-package-manager.js): replace <script> and <binary> with
  [script-name] and [binary-name] to avoid XSS scanner false positives (#43)

- fix(doc-updater.md): replace invalid 'npx ts-morph' with correct
  'npx tsx scripts/codemaps/generate.ts' since ts-morph is a library,
  not a CLI tool (#51)

Fixes #42, #43, #51
2026-01-24 01:36:02 -08:00
zerx-lab
970f8bf884 feat: cross-platform support with Node.js scripts
- Rewrite all bash hooks to Node.js for Windows/macOS/Linux compatibility
- Add package manager auto-detection (npm, pnpm, yarn, bun)
- Add scripts/lib/ with cross-platform utilities
- Add /setup-pm command for package manager configuration
- Add comprehensive test suite (62 tests)

Co-authored-by: zerx-lab
2026-01-22 23:08:07 -08:00