11 Commits

  • fix: add cwd to prettier hook, consistent process.exit(0), and stdout pass-through
    - post-edit-format.js: add cwd based on file directory so npx resolves
      correct local prettier binary
    - post-edit-typecheck.js, post-edit-format.js: replace console.log(data)
      with process.stdout.write(data) to avoid trailing newline corruption
    - Add process.exit(0) to 4 hooks for consistent termination
      (check-console-log, post-edit-console-warn, post-edit-format,
      post-edit-typecheck)
    - run-all.js: switch from execSync to spawnSync so stderr is visible
      on the success path (hook warnings were silently discarded)
    - Add 21 tests: cwd verification, process.exit(0) checks, exact
      stdout pass-through, extension edge cases, exclusion pattern
      matching, threshold boundary values (630 → 651)
  • fix: eliminate command injection in hooks, fix pass-through newline corruption, add 8 tests
    Replace shell: true with npx.cmd on Windows in post-edit-format.js and
    post-edit-typecheck.js to prevent command injection via crafted file paths.
    Replace console.log(data) with process.stdout.write(data) in
    check-console-log.js to avoid appending extra newlines to pass-through data.
  • fix: typecheck hook false positives, add 11 session-manager tests
    - Fix post-edit-typecheck.js error filtering: use relative/absolute path
      matching instead of basename, preventing false positives when multiple
      files share the same name (e.g., src/utils.ts vs tests/utils.ts)
    - Add writeSessionContent tests (create, overwrite, invalid path)
    - Add appendSessionContent test (append to existing file)
    - Add deleteSession tests (delete existing, non-existent)
    - Add sessionExists tests (file, non-existent, directory)
    - Add getSessionStats empty content edge case
    - Add post-edit-typecheck stdout passthrough test
    - Total: 391 → 402 tests, all passing
  • fix: Windows compatibility for hook scripts (execFileSync + tmux) (#215)
    * fix: Windows compatibility for hook scripts
    
    - post-edit-format.js: add `shell: process.platform === 'win32'` to
      execFileSync options so npx.cmd is resolved via cmd.exe on Windows
    - post-edit-typecheck.js: same fix for tsc invocation via npx
    - hooks.json: skip tmux-dependent hooks on Windows where tmux is
      unavailable (dev-server blocker and long-running command reminder)
    
    On Windows, execFileSync('npx', ...) without shell:true fails with
    ENOENT because Node.js cannot directly execute .cmd files. These
    hooks silently fail on all Windows installations.
    
    The tmux hooks unconditionally block dev server commands (exit 2) or
    warn about tmux on Windows where tmux is not available.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
    
    * fix: parse Claude Code JSONL transcript format correctly
    
    The session-end hook expected user messages at entry.content, but
    Claude Code's actual JSONL format nests them at entry.message.content.
    This caused all session files to be blank templates (0 user messages
    despite 136+ actual entries).
    
    - Check entry.message?.content in addition to entry.content
    - Extract tool_use blocks from assistant message.content arrays
    
    Verified with Claude Code v2.1.41 JSONL transcripts.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: ddungan <sckim@mococo.co.kr>
    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
  • 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
  • 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)
  • 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
  • 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
  • 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