Commit Graph

161 Commits

  • 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)
  • 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.
  • feat: add docker-patterns skill for containerized development
    Docker Compose for local dev, networking, volume strategies, container
    security hardening, debugging commands, and anti-patterns.
    
    Complements the existing deployment-patterns skill which covers CI/CD
    and production Dockerfiles.
    
    Closes #121
  • fix: resolve symlinks in install.sh for npm/bun bin usage
    When installed via `npm install ecc-universal`, the `ecc-install` bin
    entry creates a symlink from the package manager's bin directory to
    install.sh. The old `$(dirname "$0")` resolved to the bin directory
    instead of the actual package directory, causing `cp` to fail with
    "cannot stat '.../rules/common/.'".
    
    Now follows the symlink chain with readlink before resolving SCRIPT_DIR.
    
    Fixes #199
  • 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)
  • refactor: slim down 4 remaining oversized agents (73% reduction)
    - go-build-resolver: 368 -> 94 lines (-74%), references golang-patterns skill
    - refactor-cleaner: 306 -> 85 lines (-72%), removed project-specific rules & templates
    - tdd-guide: 280 -> 80 lines (-71%), references tdd-workflow skill
    - go-reviewer: 267 -> 76 lines (-72%), references golang-patterns skill
    
    Combined with prior round: 10 agents optimized, 3,710 lines saved total.
    All agents now under 225 lines. Largest: code-reviewer (224).
  • 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)
  • fix: use tests/run-all.js in npm test to avoid test file drift
    The package.json test script listed individual test files, which fell
    out of sync when session-manager.test.js and session-aliases.test.js
    were added to tests/run-all.js but not to package.json. Now npm test
    delegates to run-all.js so new test files are automatically included.
  • test: add 13 tests for package-manager.js untested functions
    - setProjectPackageManager: creates config, rejects unknown PM
    - setPreferredPackageManager: rejects unknown PM
    - detectFromPackageJson: invalid JSON, unknown PM name
    - getExecCommand: without args
    - getRunCommand: build, dev, and custom scripts
    - DETECTION_PRIORITY: order verification
    - getCommandPattern: install and custom action patterns
    
    Total tests: 164 → 177
  • 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
  • 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
  • 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
  • refactor: move embedded patterns from agents to skills (#174)
    Reduces the 6 largest agent prompts by 79-87%, saving ~2,800 lines
    that loaded into subagent context on every invocation.
    
    Changes:
    - e2e-runner.md: 797 → 107 lines (-87%)
    - database-reviewer.md: 654 → 91 lines (-86%)
    - security-reviewer.md: 545 → 108 lines (-80%)
    - build-error-resolver.md: 532 → 114 lines (-79%)
    - doc-updater.md: 452 → 107 lines (-76%)
    - python-reviewer.md: 469 → 98 lines (-79%)
    
    Patterns moved to on-demand skills (loaded only when referenced):
    - New: skills/e2e-testing/SKILL.md (Playwright patterns, POM, CI/CD)
    - Existing: postgres-patterns, security-review, python-patterns
  • fix: handle Windows EOF error in large-input hook test
    Windows pipes raise EOF instead of EPIPE when the child process
    exits before stdin finishes flushing. Added EOF to the ignored
    error codes in runHookWithInput.
  • docs: enhance 5 thin commands and add Rust API example
    Commands enhanced with multi-language support, error recovery strategies,
    and structured step-by-step workflows:
    - build-fix: build system detection table, fix loop, recovery strategies
    - test-coverage: framework detection, test generation rules, before/after report
    - refactor-clean: safety tiers (SAFE/CAUTION/DANGER), multi-language tools
    - update-codemaps: codemap format spec, diff detection, metadata headers
    - update-docs: source-of-truth mapping, staleness checks, generated markers
    
    New example:
    - rust-api-CLAUDE.md: Axum + SQLx + PostgreSQL with layered architecture,
      thiserror patterns, compile-time SQL verification, integration test examples
  • docs: add token optimization guide with recommended settings (#175)
    Adds a comprehensive Token Optimization section to the README with:
    - Recommended settings (model, MAX_THINKING_TOKENS, AUTOCOMPACT_PCT)
    - Daily workflow commands table (/model, /clear, /compact, /cost)
    - Strategic compaction guidance (when to compact vs not)
    - Context window management (MCP tool description costs)
    - Agent Teams cost warning
  • fix: add global ignores to ESLint config for dist and cursor dirs
    Prevent ESLint from parsing .opencode/dist/ (ES modules with
    sourceType: commonjs mismatch) and .cursor/ (duplicated files).
    Uses flat config global ignores pattern (standalone ignores object).
  • fix: pass transcript_path via stdin JSON in integration tests (#209)
    Integration tests were still passing CLAUDE_TRANSCRIPT_PATH as an env
    var, but evaluate-session.js now reads transcript_path from stdin JSON.
    Also improves strategic-compact skill with decision guide and survival table.
  • docs: add 'When to Activate' sections to 14 skill definitions
    Add activation triggers to skills that were missing them, helping
    Claude Code determine when to load each skill contextually.
  • 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
  • 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.
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • docs: expand AgentShield section with hackathon context and add sponsors
    - Expand AgentShield ecosystem section with Opus 4.6 three-agent pipeline
      details, 5 scan categories, and 4 output formats
    - Add hackathon badge to header stats
    - Add sponsors section before star history
  • 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.
  • chore: rename opencode plugin to ecc-universal and add .npmignore
    - Rename opencode-ecc to ecc-universal across package.json, index.ts,
      README.md, and MIGRATION.md for consistent branding
    - Add .npmignore to exclude translation READMEs, release scripts, and
      plugin dev notes from npm package
  • fix: rename opencode package from opencode-ecc to ecc-universal
    Update all references in .opencode/ to use the published npm package
    name ecc-universal instead of the old opencode-ecc name.
  • chore: sync .cursor/ directory with latest agents, commands, and skills
    - Sync 13 agent files with updated descriptions and configurations
    - Sync 23 command files with latest YAML frontmatter and content
    - Sync 7 skill SKILL.md files with proper YAML frontmatter quoting
    - Copy missing cpp-testing and security-scan skills to .cursor/
    - Fix integration tests: send matching input to blocking hook test and
      expect correct exit code 2 (was 1)
  • 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 $$)
  • docs: add hooks guide, expand planner agent, add Django example
    - Add hooks/README.md: comprehensive hook documentation with input schema,
      customization guide, 4 ready-to-use hook recipes, and cross-platform notes
    - Expand planner agent with full worked example (Stripe subscriptions plan)
      and sizing/phasing guidance (119 → 212 lines)
    - Add Django REST API example config (DRF + Celery + pytest + Factory Boy)
    - Update README directory tree with new files
  • 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
  • docs: expand Spring Boot skills and add Go microservice example
    - springboot-security: add code examples for authorization, input validation,
      SQL injection prevention, password encoding, CORS, rate limiting, and secrets
      management (119 → 261 lines)
    - springboot-verification: add unit test, Testcontainers integration test,
      MockMvc API test patterns, and security scan grep commands (100 → 222 lines)
    - Add Go microservice example (gRPC + PostgreSQL + clean architecture)
    - Update README directory tree with new example
  • fix: sync .cursor observe.sh and fix suggest-compact.sh session tracking
    - Sync .cursor/observe.sh with corrected main version (use stdin pipe
      instead of broken heredoc json.loads pattern)
    - Fix suggest-compact.sh to use CLAUDE_SESSION_ID instead of $$ which
      gives a new PID per invocation, preventing counter from incrementing
  • docs: improve README with agent guide, FAQ, and fix component counts
    - Fix inaccurate counts: 13 agents (was 15+), 34 skills (was 30+), 31 commands (was 30)
    - Add "Which Agent Should I Use?" decision table with common workflows
    - Add FAQ section addressing top recurring issues (hooks, context window, cross-platform)
    - Add 5 missing skills and 7 missing commands to directory tree listing
    - Expand code-reviewer agent with React/Next.js, Node.js patterns, and confidence filtering
    - Add real-world SaaS example (Next.js + Supabase + Stripe) in examples/
  • test: update getSelectionPrompt test for new no-spawn behavior
    The prompt no longer lists "Available package managers" (which required
    spawning processes) — it now shows "Supported package managers" and
    mentions lock file detection as a configuration option.
    
    All 69 tests pass.
  • 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
  • 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)
  • docs: Add Skills Directory link to zh-CN and zh-TW README (#206)
    * Update links and add skills directory in README
    
    * Add skills directory link to README in Chinese
  • 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.