Commit Graph

149 Commits

  • feat(hooks): add config protection hook to block linter config manipulation (#758)
    * feat(hooks): add config protection hook to block linter config manipulation
    
    Agents frequently modify linter/formatter configs (.eslintrc, biome.json,
    .prettierrc, .ruff.toml, etc.) to make checks pass instead of fixing
    the actual code.
    
    This PreToolUse hook intercepts Write/Edit/MultiEdit calls targeting
    known config files and blocks them with a steering message that directs
    the agent to fix the source code instead.
    
    Covers: ESLint, Prettier, Biome, Ruff, ShellCheck, Stylelint, and
    Markdownlint configs.
    
    Fixes #733
    
    * Address review: fix dead code, add missing configs, export run()
    
    - Removed pyproject.toml from PROTECTED_FILES (was dead code since
      it was also in PARTIAL_CONFIG_FILES). Added comment explaining why
      it's intentionally excluded.
    - Removed PARTIAL_CONFIG_FILES entirely (no longer needed).
    - Added missing ESLint v9 TypeScript flat configs: eslint.config.ts,
      eslint.config.mts, eslint.config.cts
    - Added missing Prettier ESM config: prettier.config.mjs
    - Exported run() function for in-process execution via run-with-flags,
      avoiding the spawnSync overhead (~50-100ms per call).
    
    * Handle stdin truncation gracefully, log warning instead of fail-open
    
    If stdin exceeds 1MB, the JSON would be malformed and the catch
    block would silently pass through. Now we detect truncation and
    log a warning. The in-process run() path is not affected.
  • fix: safe Codex config sync — merge AGENTS.md + add-only MCP servers (#723)
    * fix: replace bash TOML surgery with Node add-only MCP merge
    
    The old sync script used awk/sed to remove and re-append MCP server
    sections in config.toml, causing credential extraction races, duplicate
    TOML tables, and 3 fragile code paths with 9 remove_section_inplace
    calls each.
    
    Replace with a Node script (scripts/codex/merge-mcp-config.js) that
    uses @iarna/toml to parse the config, then appends only missing ECC
    servers — preserving all existing content byte-for-byte. Warns on
    config drift, supports legacy aliases (context7 → context7-mcp), and
    adds --update-mcp flag for explicit refresh.
    
    Generated with [Claude Code](https://claude.ai/code)
    via [Happy](https://happy.engineering)
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    Co-Authored-By: Happy <yesreply@happy.engineering>
    
    * fix: address PR #723 review findings for Codex MCP merge
    
    - Use package-manager abstraction (scripts/lib/package-manager.js)
      instead of hardcoding pnpm — respects CLAUDE_PACKAGE_MANAGER,
      lock files, and project config
    - Add Yarn 1.x fallback to npx (yarn dlx unsupported in classic)
    - Add missing exa server to match .codex/config.toml baseline
    - Wire up findSubSections for --update-mcp nested subtable removal
      (fixes Greptile P1: Object.keys only returned top-level keys)
    - Fix resolvedLabel to prefer canonical entry over legacy alias
      when both exist (fixes context7/context7-mcp spurious warning)
    - Fix removeSectionFromText to handle inline TOML comments
    - Fix dry-run + --update-mcp to show removals before early return
    - Update README parity table: 4 → 7 servers, TOML-parser-based
    - Add non-npm install variants to README Codex quick start
    - Update package-lock.json for @iarna/toml
    
    Generated with [Claude Code](https://claude.ai/code)
    via [Happy](https://happy.engineering)
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    Co-Authored-By: Happy <yesreply@happy.engineering>
    
    * fix: address PR #723 review comments (preflight, marker validation)
    
    - Add Node.js and merge-mcp-config.js to preflight checks so the
      script fails fast before partial writes (CodeRabbit)
    - Validate marker counts: require exactly 1 BEGIN + 1 END in correct
      order for clean replacement (CodeRabbit)
    - Corrupted markers: strip all marker lines and re-append fresh block,
      preserving user content outside markers instead of overwriting
    - Move MCP_MERGE_SCRIPT to preflight section, remove duplicate
    
    Generated with [Claude Code](https://claude.ai/code)
    via [Happy](https://happy.engineering)
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    Co-Authored-By: Happy <yesreply@happy.engineering>
    
    ---------
    
    Co-authored-by: Claude <noreply@anthropic.com>
    Co-authored-by: Happy <yesreply@happy.engineering>
  • fix(install): add rust, cpp, csharp to legacy language alias map (#747)
    * fix(install): add rust, cpp, csharp to legacy language alias map
    
    The legacy installer compatibility layer in install-manifests.js was
    missing entries for rust, cpp, and csharp — languages that have
    rules/ directories and (for rust/cpp) install-components.json entries.
    
    Running `./install.sh rust` fails with "Unknown legacy language: rust"
    because LEGACY_LANGUAGE_ALIAS_TO_CANONICAL and
    LEGACY_LANGUAGE_EXTRA_MODULE_IDS didn't include these languages.
    
    Fixes the issue reported in #694 by @mpiton.
    
    Generated with [Claude Code](https://claude.ai/code)
    via [Happy](https://happy.engineering)
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    Co-Authored-By: Happy <yesreply@happy.engineering>
    
    * fix(install): complete csharp legacy support and add resolution tests
    
    - Add lang:csharp component to install-components.json with
      framework-language module (matching cpp/rust pattern)
    - Update csharp mapping in LEGACY_LANGUAGE_EXTRA_MODULE_IDS from
      empty array to ['framework-language']
    - Add end-to-end resolution tests for rust, cpp, and csharp verifying
      framework-language module is included in resolved moduleIds
    
    Addresses review feedback from Copilot, Greptile, CodeRabbit, and Cubic.
    
    Generated with [Claude Code](https://claude.ai/code)
    via [Happy](https://happy.engineering)
    
    Co-Authored-By: Claude <noreply@anthropic.com>
    Co-Authored-By: Happy <yesreply@happy.engineering>
    
    ---------
    
    Co-authored-by: Claude <noreply@anthropic.com>
    Co-authored-by: Happy <yesreply@happy.engineering>
  • fix: codex sync merges AGENTS.md instead of replacing it (#715)
    The sync script previously overwrote ~/.codex/AGENTS.md on every run,
    destroying any user-authored content. This adds marker-based merging
    (<!-- BEGIN ECC --> / <!-- END ECC -->) so only the ECC-managed section
    is replaced on subsequent runs, preserving user content outside the
    markers.
    
    Merge logic:
    - No file → create with markers
    - Both markers present (ordered, CRLF-safe) → replace only the ECC section
    - BEGIN without END (corrupted) → full replace (backup saved)
    - No markers at all → append ECC block (preserves existing content)
    
    Also fixes:
    - Symlink preservation: uses cat > instead of mv to write through symlinks
    - CRLF handling: strips \r in marker detection to handle Windows-edited files
    - Marker ordering: validates BEGIN appears before END, not just that both exist
    
    The legacy heading-match heuristic was intentionally removed per council
    review: any unmarked file is either user-authored (append is safe) or
    legacy ECC-generated (duplicates once, deduplicates on next run via
    markers). A timestamped backup is always saved before any mutation.
    
    Generated with [Claude Code](https://claude.ai/code)
    via [Happy](https://happy.engineering)
    
    Co-authored-by: Claude <noreply@anthropic.com>
    Co-authored-by: Happy <yesreply@happy.engineering>
  • feat: agent description compression with lazy loading (#696)
    * feat: add agent description compression with lazy loading (#491)
    
    Agent descriptions consume ~26k tokens (121KB across 27 agents). This adds
    a compression library with three modes:
    - catalog: metadata only (~2-3k tokens) for agent selection
    - summary: metadata + first paragraph (~4-5k tokens) for routing
    - full: no compression, for when agent is invoked
    
    Includes lazy-load function to fetch full agent body on demand.
    21 tests covering parsing, compression, filtering, and real agents dir.
    
    * fix: update JSDoc to include all stats fields in buildAgentCatalog
    
    Add compressedBytes and mode to the documented return type, matching
    the actual implementation.
  • fix: auto-detect ECC root from plugin cache when CLAUDE_PLUGIN_ROOT is unset (#547) (#691)
    When ECC is installed as a Claude Code plugin via the marketplace,
    scripts live in the plugin cache (~/.claude/plugins/cache/...) but
    commands fallback to ~/.claude/ which doesn't have the scripts.
    
    Add resolve-ecc-root.js with a 3-step fallback chain:
      1. CLAUDE_PLUGIN_ROOT env var (existing)
      2. Standard install at ~/.claude/ (existing)
      3. NEW: auto-scan the plugin cache directory
    
    Update sessions.md and skill-health.md commands to use the new
    inline resolver. Includes 15 tests covering all fallback paths
    including env var priority, standard install, cache discovery,
    and the compact INLINE_RESOLVE used in command .md files.
  • feat: agent compression, inspection logic, governance hooks (#491, #485, #482) (#688)
    Implements three roadmap features:
    
    - Agent description compression (#491): New `agent-compress` module with
      catalog/summary/full compression modes and lazy-loading. Reduces ~26k
      token agent descriptions to ~2-3k catalog entries for context efficiency.
    
    - Inspection logic (#485): New `inspection` module that detects recurring
      failure patterns in skill_runs. Groups by skill + normalized failure
      reason, generates structured reports with suggested remediation actions.
      Configurable threshold (default: 3 failures).
    
    - Governance event capture hook (#482): PreToolUse/PostToolUse hook that
      detects secrets, policy violations, approval-required commands, and
      elevated privilege usage. Gated behind ECC_GOVERNANCE_CAPTURE=1 flag.
      Writes to governance_events table via JSON-line stderr output.
    
    59 new tests (16 + 16 + 27), all passing.
  • fix: strip ANSI escape codes from session persistence hooks (#642) (#684)
    Windows terminals emit control sequences (cursor movement, screen
    clearing) that leaked into session.tmp files and were injected
    verbatim into Claude's context on the next session start.
    
    Add a comprehensive stripAnsi() to utils.js that handles CSI, OSC,
    charset selection, and bare ESC sequences. Apply it in session-end.js
    (when extracting user messages from the transcript) and in
    session-start.js (safety net before injecting session content).
  • feat: implement --with/--without selective install flags (#679)
    Add agent: and skill: component families to the install component
    catalog, enabling fine-grained selective install via CLI flags:
    
      ecc install --profile developer --with lang:typescript --without capability:orchestration
      ecc install --with lang:python --with agent:security-reviewer
    
    Changes:
    - Add agent: family (9 entries) and skill: family (10 entries) to
      manifests/install-components.json for granular component addressing
    - Update install-components.schema.json to accept agent: and skill:
      family prefixes
    - Register agent and skill family prefixes in COMPONENT_FAMILY_PREFIXES
      (scripts/lib/install-manifests.js)
    - Add 41 comprehensive tests covering CLI parsing, request normalization,
      component catalog validation, plan resolution, target filtering,
      error handling, and end-to-end install with --with/--without flags
    
    Closes #470
  • fix: resolve 8 test failures on main (install pipeline, orchestrator, repair) (#564)
    - Add duplicate slug detection in buildOrchestrationPlan to reject
      worker names that collapse to the same slug
    - Use buildTemplateVariables() for launcher command interpolation
      so _sh and _raw suffixes are available in templates
  • feat: add Codex CLI customization scripts (#336)
    * chore(codex): add global ecc sync script and pnpm mcp config
    
    * chore(codex): include codex supplement when syncing agents
    
    * feat(codex): add global git safety hooks and QA/rule prompt packs
    
    * feat(codex): add global regression sanity check command
    
    ---------
    
    Co-authored-by: TGreen87 <your-email@example.com>
  • feat(design): skill health dashboard mockup (#518)
    * feat(Design): skill health dashboard mockup
    
    * fix(comments): code according to comments
  • fix: export run() to avoid Windows spawnSync issues (#431)
    - session-end-marker.js now exports run() function
    - Enables in-process execution via run-with-flags.js
    - Avoids spawnSync cross-platform issues on Windows
    - Maintains backward compatibility with direct CLI execution
    
    Fixes #429
    
    Co-authored-by: 阳虎 <yanghu@yanghudeMacBook-Pro.local>
  • fix(ci): enforce catalog count integrity (#525)
    * fix(ci): enforce catalog count integrity
    
    * test: harden catalog structure parsing
  • Add PowerShell installer wrapper and update documentation (#532)
    * Add install.ps1 PowerShell wrapper and tests
    
    Add a Windows-native PowerShell wrapper (install.ps1) that resolves symlinks and delegates to the Node-based installer runtime. Update README with PowerShell usage examples and cross-platform npx entrypoint guidance. Point the ecc-install bin to the Node installer (scripts/install-apply.js) in package.json (and refresh package-lock), include install.ps1 in package files, and add tests: a new install-ps1.test.js and a tweak to install-sh.test.js to skip on Windows. These changes provide native Windows installer support while keeping npm-compatible cross-platform invocation.
    
    * Improve tests for Windows HOME/USERPROFILE
    
    Make tests more cross-platform by ensuring HOME and USERPROFILE are kept in sync and by normalizing test file paths for display.
    
    - tests/lib/session-adapters.test.js: set USERPROFILE when temporarily setting HOME and restore previous USERPROFILE on teardown.
    - tests/run-all.js: use a normalized displayPath (forward-slash separated) for logging and error messages so output is consistent across platforms.
    - tests/scripts/ecc.test.js & tests/scripts/session-inspect.test.js: build envOverrides from options.env and add HOME <-> USERPROFILE fallbacks so spawned child processes receive both variables when only one is provided.
    
    These changes prevent test failures and inconsistent logs on Windows where USERPROFILE is used instead of HOME.
    
    * Fix Windows paths and test flakiness
    
    Improve cross-platform behavior and test stability.
    
    - Remove unused createLegacyInstallPlan import from install-lifecycle.js.
    - Change resolveInstallConfigPath to use path.normalize(path.join(cwd, configPath)) to produce normalized relative paths.
    - Tests: add toBashPath and normalizedRelativePath helpers to normalize Windows paths for bash and comparisons.
    - Make cleanupTestDir retry rmSync on transient Windows errors (EPERM/EBUSY/ENOTEMPTY) with short backoff using sleepMs.
    - Ensure spawned test processes receive USERPROFILE and convert repo/detect paths to bash format when invoking bash.
    
    These changes reduce Windows-specific failures and flakiness in the test suite and tidy up a small unused import.
  • fix: resolve all CI test failures (19 fixes across 6 files) (#519)
    - canonical-session: fall back to JSON file recording when the loaded
      state-store module has no writer methods (factory vs instance)
    - install-executor: skip node_modules and .git dirs in listFilesRecursive
      to prevent ETIMEDOUT copying thousands of .opencode dependency files
    - ecc.js: increase maxBuffer to 10MB for spawned subcommands to prevent
      ENOBUFS on large install plan JSON output
    - install-apply.test: update Cursor and Antigravity path assertions to
      match flattened rule layout and remapped dirs (workflows, skills)
    - ecc.test: increase maxBuffer in test runner to handle large output
    - orchestrate-codex-worker.sh: guard against unreadable task file before
      cat, write failure status and handoff artifacts on early exit
  • feat: add SQLite state store and query CLI (#510)
    * feat: add SQLite state store and ECC status CLI
    
    * fix: replace better-sqlite3 with sql.js to eliminate native module CI failures
    
    better-sqlite3 requires native C++ compilation (node-gyp, prebuild-install)
    which fails in CI across npm/pnpm on all platforms:
    - npm ci: lock file out of sync with native transitive deps
    - pnpm: native bindings not found at runtime
    - Windows: native compilation fails entirely
    
    sql.js is a pure JavaScript/WASM SQLite implementation with zero native
    dependencies. The adapter in index.js wraps the sql.js API to match the
    better-sqlite3 interface used by migrations.js and queries.js.
    
    Key implementation detail: sql.js db.export() implicitly ends active
    transactions, so the adapter defers disk writes (saveToDisk) until
    after transaction commit via an inTransaction guard flag.
    
    createStateStore is now async (sql.js requires async WASM init).
    Updated status.js, sessions-cli.js, and tests accordingly.
  • feat: strengthen install lifecycle and target adapters (#512)
    * fix: strengthen install lifecycle adapters
    
    * fix: restore template content on uninstall
  • feat: self-improving skills loop — observe, inspect, amend, evaluate
    - Add skill health observation layer (execution logging, success/failure tracking)
    - Add skill health inspector (trace recurring failures across runs)
    - Add amendify mechanism (propose SKILL.md patches from failure evidence)
    - Add evaluation scaffolding (compare amended vs original performance)
    - Wire into session-inspect CLI: skills:health, skills:amendify, skills:evaluate
    - 1145/1145 tests passing (+3 new)
  • feat: expand session adapter registry with structured targets
    - Registry accepts { type, value } structured targets
    - Add --list-adapters and --target-type CLI flags to session-inspect
    - Export adapter type from claude-history and dmux-tmux adapters
    - 71 new session adapter tests, 34 new session-inspect tests
    - All 1142 tests passing
  • Merge remote-tracking branch 'origin/main' into feat/optimize-biome-hooks
    # Conflicts:
    #	tests/hooks/hooks.test.js
    #	tests/run-all.js
  • feat: architecture improvements — test discovery, hooks schema, catalog, command map, coverage, cross-harness docs
    - AGENTS.md: sync skills count to 65+
    - tests/run-all.js: glob-based test discovery for *.test.js
    - scripts/ci/validate-hooks.js: validate hooks.json with ajv + schemas/hooks.schema.json
    - schemas/hooks.schema.json: hookItem.type enum command|notification
    - scripts/ci/catalog.js: catalog agents, commands, skills (--json | --md)
    - docs/COMMAND-AGENT-MAP.md: command → agent/skill map
    - docs/ARCHITECTURE-IMPROVEMENTS.md: improvement recommendations
    - package.json: ajv, c8 devDeps; npm run coverage
    - CONTRIBUTING.md: Cross-Harness and Translations section
    - .gitignore: coverage/
    
    Made-with: Cursor
  • refactor: deduplicate config lists and unify resolveFormatterBin branches
    Extract BIOME_CONFIGS and PRETTIER_CONFIGS as shared constants to eliminate
    duplication between PROJECT_ROOT_MARKERS and detectFormatter(). Unify the
    biome/prettier branches in resolveFormatterBin() via a FORMATTER_PACKAGES
    map. Remove redundant path.resolve() in quality-gate.js.
  • fix(hooks): add Windows .cmd support with shell injection guard
    Handle Windows .cmd shim resolution via spawnSync with strict path
    validation. Removes shell:true injection risk, uses strict equality,
    and restores .cmd support with path injection guard.