Commit Graph

2113 Commits

  • Merge pull request #2202 from stroland02/feat-ml-adoption
    feat(skills): add ml-adoption-playbook skill. Catalog manifests/counts reconciled via catalog:sync.
  • feat(agents): add spec-miner agent for brownfield spec extraction (#2253)
    * feat(agents): add spec-miner agent for brownfield spec extraction
    
    Mines behavioral specs (Requirements + Invariants) from existing codebases
    without OpenSpec. Fully self-bootstrapping with sample-and-expand token
    strategy. Produces flat, delta-ready spec.md files with machine-parseable
    metadata (id, entities, enforced, depends_on, triggers).
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * docs: bump agent catalog count from 64 to 65 for spec-miner
    
    All documentation and plugin manifests now reflect the new agent total.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: add spec-miner to routing table and clarify id field requirement
    
    - Add spec-miner to AGENTS.md agent table and orchestration hints
    - Fix id field in output template: was marked [optional] but Rule #7
      requires it when enforced is known
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: update catalog skills count from 261 to 262 across all docs
    
    The upstream added a 262nd skill but documentation references across 7 files
    still reported 261. The CI validate step (scripts/ci/catalog.js --text) caught
    the mismatch — this only runs on PRs, not on direct pushes to main.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: replace emoji characters with text equivalents in spec-miner agent
    
    The unicode safety check (check-unicode-safety.js) blocks emoji characters.
    Replace  with FAIL: per the project's targeted replacement convention.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: add Write tool to spec-miner agent tools list
    
    The agent generates spec output files at openspec/specs/<capability>/spec.md
    and requires the Write tool to create them.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: address review bot comments - tool guardrails and metadata schema consistency
    
    - Add Tool guardrails section: scoping Write to openspec/specs/ path, Bash to read-only
    - Fix deferred/uncertainty comments to follow key: value schema (deferred: file list, uncertainty: reason)
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: strengthen Prompt Defense Baseline for repository content and Bash boundaries
    
    Add two defense points: treat all repo content as untrusted prompt-injection
    vector, and explicitly reject Bash commands that mutate, exfiltrate, or write
    outside the allowed openspec/specs/ path.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: strip explanatory prose from id metadata comment to preserve key:value format
    
    The id comments included explanatory text after the value, which would be
    stored verbatim in copied specs and break stable delta matching. The
    explanation is already covered by Format Rule #7.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: restore README.md to upstream baseline with only catalog count changes
    
    The README was corrupted during cherry-pick conflict resolution — an older fork
    version was introduced, changing release notes links, badge URLs, sponsor
    sections, and other content. Restore to upstream/main (5b173d2) and re-apply
    only the agent count (64→65) using catalog.js --write.
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    * fix: restore all catalog files to upstream baseline, keep only intentional changes
    
    The cherry-pick during rebase introduced a stale fork version of multiple files
    via git checkout --theirs conflict resolution. Restore from upstream/main and
    re-apply only:
    
    - Agent counts: 64→65 (all 7 catalog-tracked files)
    - Skills counts: 261→262 (where needed)
    - AGENTS.md: spec-miner routing table + orchestration hint (our additions)
    
    This reverts unintended regressions:
    - Version downgrades (2.0.0 → 2.0.0-rc.1) in marketplace.json, plugin.json,
      AGENTS.md, docs/zh-CN/AGENTS.md, docs/zh-CN/README.md
    - Badge URL changes (api.ecc.tools dynamic → hardcoded) in Chinese READMEs
    - Deleted v2.0.0 stable release sections in Chinese READMEs
    - Wrong release notes path (2.0.0-rc.1 → 2.0.0) in README.md
    
    Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: lege962 <1515808962@qq.com>
    Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
  • feat: add Rails 8 application CLAUDE.md example (#2258)
    * feat: add Rails 8 application CLAUDE.md example
    
    Adds examples/rails-app-CLAUDE.md as a reference template for Rails 8 applications.
    
    - Add examples/rails-app-CLAUDE.md: full-stack Rails 8 template covering Hotwire (Turbo + Stimulus), ViewComponent, the Solid stack (SolidQueue, SolidCache, SolidCable), service objects, query objects, and Pundit authorization
    - Aligns with existing rules/ruby/ conventions (Rails Way first, SolidQueue for greenfield, Hotwire-preferred, Rails 8 generated authentication)
    - Includes five Key Patterns code blocks: service object, skinny controller, query object, background job, RSpec test
    
    	new file:   examples/rails-app-CLAUDE.md
    
    * fix(examples): correct Rails 8 CLAUDE.md examples for auth, transactions, and terminology
    
    - Remove Django `select_related` terminology in favor of direct Rails methods
    - Replace `authenticate_user!` (Devise-only) with `require_authentication` (Rails 8 generator default), with inline comment noting Devise as the alternative
    - Move `send_notifications` outside the transaction block in the service object example so it only runs after a confirmed commit; safe with both SolidQueue and Sidekiq
    - Remove `puts` from the N+1 BAD/GOOD example to align with the Ruby Conventions rule that bans `puts` in committed code
    
    * fix(examples): improve idempotency, notification handling, and job argument guidance
    
    - Wrap send_notifications in its own rescue block so notification failures are logged but do not raise out of the service object, preserving the Result-based error handling pattern
    - Update the background job example to show an idempotency_key passed to the external API call, so the example is retry-safe by default rather than relying on a comment to flag the limitation
    - Add a Background Jobs rule about pairing local idempotency checks with API-level idempotency tokens and considering with_lock for high-concurrency scenarios
    - Soften the absolute "never records" claim for job arguments to explain the real reason (ActiveJob::DeserializationError when records are deleted between enqueue and execute)
    
    * fix(examples): use exported_at.present? to match the column the example writes
    
    The previous `exported?` check assumed a predicate method on the model that this example does not define. Using `exported_at.present?` keeps the guard consistent with the column the next line writes to in `update!(exported_at: Time.current)`.
  • feat(rules): add vue and nuxt rule sets (#2250)
    * feat(rules): add vue and nuxt rule sets
    
    Add rules/vue/ and rules/nuxt/, each with the standard 5-file layout (coding-style, hooks, patterns, security, testing) that extends common/, following the Adding a New Language convention in rules/README.md.
    
    Vue rules reference the frontend-patterns and vite-patterns skills. Nuxt rules reference the nuxt4-patterns and vite-patterns skills. Content is concise (1.5 to 4 KB per file) since rules load as always-on context.
    
    * fix(rules): address PR review on vue and nuxt rule sets
    
    - nuxt/coding-style: generalize the srcDir-override note (drop project-specific 'this repo' phrasing so it is correct for any Nuxt project).
    
    - vue/hooks: add **/*.ts and **/*.tsx to paths so the lint/typecheck guidance loads when editing composables and stores.
    
    - nuxt/hooks: add **/*.vue to paths (covers pages/layouts/components) and wrap nuxi typecheck in a timeout, mirroring web/hooks.md.
    
    - nuxt/security: tighten the /security-review auto-trigger scope to external fetch, credential handling, and sensitive mutations, with examples.
    
    - nuxt/testing: correct 'Vitest-only' to note built-in Playwright E2E, and drop the @nuxt/test-utils version pin.
    
    - README: register vue and nuxt in the structure tree and install examples.
    
    Skipped: 'X specific' -> 'X-specific' hyphenation (all existing rule sets use the unhyphenated form, changing only vue/nuxt would be inconsistent); repeating the 80%/TDD mandate in nuxt/testing (already inherited from common/testing.md).
  • feat(opencode): 全面升级OpenCode集成 (#2251)
    - 修复ecc-hooks.ts中的硬编码ECC_VERSION(从package.json读取)
    - 改进错误处理机制(统一模式、详细错误信息)
    - 增强类型安全(添加ToolArgs、ToolInput等类型定义)
    - 改进跨平台兼容性(支持macOS、Windows、Linux)
    - 添加dependency-analyzer工具(依赖分析)
    - 改进format-code工具(错误处理、跨平台支持)
    - 改进lint-check工具(错误处理、跨平台支持)
    - 更新文档(代理26个、工具8个、命令26个)
    - 添加工具测试(6个测试用例)
    - 改进现有测试(7个测试用例)
    
    所有测试通过(16/16)
    
    Co-authored-by: Pual-LI-6 <dj2112236494@outlook.com>
  • Finalize and enhance SLSA generic generator workflow (#2197)
    * Add SLSA generic generator workflow
    
    * ci: finalize SLSA generator and fix bun test timeout
    
    - Harden SLSA workflow with persist-credentials: false and pinned actions
    - Update SLSA workflow to build real npm artifacts and fix digest outputs
    - Increase trae-install test timeout to prevent ETIMEDOUT under Bun
    - Fix Validate Components security violation in SLSA workflow
    
    * ci: finalize SLSA generator and fix bun test timeout
    
    - Harden SLSA workflow with persist-credentials: false and pinned actions
    - Update SLSA workflow to build real npm artifacts and fix digest outputs
    - Rename workflow to "SLSA generic generator workflow #1"
    - Increase trae-install test timeout to prevent ETIMEDOUT under Bun
    - Fix Validate Components security violation in SLSA workflow
    
    * Update generator-generic-ossf-slsa3-publish.yml
    
    Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
    
    * generator-generic-ossf-slsa3-publish.yml
    
    * .github/workflows/generator-generic-ossf-slsa3-publish.yml
    
    Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
    
    * Update .github/workflows/generator-generic-ossf-slsa3-publish.yml
    
    Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
    Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
  • fix: add plugin cache health check (#2249)
    * fix: add plugin cache health check
    
    * fix: harden plugin cache diagnostics
    
    * fix: reject escaping plugin cache refs
    
    * test: remove unused plugin cache fixture
  • feat: add dry-run mode for hook execution (#2116) (#2188)
    - Global --dry-run flag and ECC_DRY_RUN=1 env var
    - Enriched preview: shows target file path, tool name, and command
    - --dry-run stripped from argv so command routing works correctly
    - Handles non-JSON and empty stdin gracefully (session/stop hooks)
    - 10 tests covering isDryRun(), hook gating, enriched output, CLI routing
  • feat: add web capabilities dashboard (#2100)
    * feat: add web capabilities dashboard with agents, skills, commands, MCPs, rules, and hooks
    
    * fix: address code review - XSS, env exposure, port validation, error handling, packaging
    
    * add tests for dashboard
  • docs: add MCP server and tools integration for tinystruct (#2244)
    * docs: add MCP server and tools integration for tinystruct
    
    * Update the doc to specify the package for apis and security reminder, checks for prompt.
  • docs(skills): document tdd plan handoff evidence (#2235)
    * docs(skills): document tdd plan handoff evidence
    
    Address issue #2138 by clarifying how tdd-workflow should continue from a plan file, preserve human-readable test guarantees, and retain RED/GREEN evidence across squash merges.
    
    * docs(skills): harden tdd plan handoff guidance
    
    Address review feedback on #2235: use angle-bracket argument hint, treat plan files as untrusted input, and prefer project-local documentation paths for TDD evidence reports.
    
    * docs(skills): clarify plan handoff injection guard
    
    Address review feedback by explicitly stating that plan file content is data, not AI instructions, and that validation commands from untrusted plans require sanitization and approval before execution.
    
    * Update skills/tdd-workflow/SKILL.md
    
    Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
    
    * docs(skills): address tdd workflow review nits
    
    Clarify plan handoff safety decisions, remove redundant untrusted-input wording, and show consistent TDD evidence path examples.
    
    ---------
    
    Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • feat(browser-qa): read-only safety default, baseline-or-die, honest a11y scope (#2186)
    Additive-only hardening of skills/browser-qa/SKILL.md.
    
    Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
  • fix: sanitize subprocess call in runner.py (#2149)
    * fix: V-001 security vulnerability
    
    Automated security fix generated by OrbisAI Security
    
    * fix: sanitize subprocess call in runner.py
    
    The runner
    
    * fix: address PR review comments on V-001 allowlist and test coverage
    
    Remove dangerous interpreters (python, python3, node, curl, wget) from
    ALLOWED_SETUP_EXECUTABLES — they can execute arbitrary code via argument
    flags and are not needed for sandbox setup. Rewrite test_invariant_runner
    to call _setup_sandbox directly instead of spawning runner.py as a
    subprocess (which had no __main__ entrypoint and never exercised the fix).
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
  • fix(security): add host/origin allowlist + validate git refs + quote workflow input (#2185)
    Three defense-in-depth fixes around untrusted input flowing to subprocess execution:
    
    1. **Control-pane HTTP server (scripts/lib/control-pane/server.js)**
       The local control-pane API binds to 127.0.0.1 but had no Host or Origin
       validation, so a DNS-rebinding attack from a malicious website could pivot
       into the loopback endpoints — including POST /api/actions/:id, which spawns
       'cargo run -- graph ...' with caller-supplied query strings. Add a hostname
       allowlist (loopback variants plus the explicitly configured --host) and
       reject mismatched Host (421) or non-loopback Origin (403) before any route
       handler runs.
    
    2. **OpenCode git-summary tool (.opencode/tools/git-summary.ts)**
       The tool was building 'git diff ${baseBranch}...HEAD --stat' with execSync
       and a raw model-supplied baseBranch string. Switch run() to execFileSync
       with an args array (no shell), validate baseBranch against a conservative
       git-ref allowlist (rejects shell metacharacters, leading -, embedded ..),
       and clamp the depth arg to a small positive integer before interpolating
       into 'git log --oneline -<N>'.
    
    3. **Reusable test workflow (.github/workflows/reusable-test.yml)**
       The 'Install dependencies' step interpolated ${{ inputs.package-manager }}
       directly into a bash 'case' and into an echo, so a downstream caller that
       forwarded attacker-controllable input could inject into the runner. Move
       the input into a PACKAGE_MANAGER env var and reference $PACKAGE_MANAGER
       inside the script per the GitHub script-injection guidance.
    
    Detected by Aeon + semgrep p/security-audit (host check via threat-model
    manual-review axis; git-summary via detect-child-process; workflow via
    run-shell-injection).
    
    Verification: node tests/run-all.js — 2686/2687 pre-existing tests pass; the
    one failure (observe.sh legacy output fallback) reproduces on main without
    this branch applied. Added 2 new control-pane tests covering the allowlist
    classifier and the DNS-rebinding-gate behavior end-to-end.
    
    ---
    Filed by [Aeon](https://github.com/aaronjmars/aeon-aaron).
    
    Co-authored-by: aeonframework <aeon@aaronjmars.com>
  • Remove model version numbers (#2144)
    Remove model version numbers so that the rules stay relevant as the new models are released
  • fix(skills): replace star ratings with ASCII N/5 (#2194)
    Change-Id: I72b7d094bb982070706595255536b69aa5998862
  • fix: prevent IOC scanner false positives on hook filenames and scan .cursor configs (#2245)
    * fix: prevent IOC scanner false positives on hook filenames and scan .cursor configs
    
    The supply-chain IOC scanner matched CRITICAL_TEXT_INDICATORS with plain
    substring search, so legitimate hook filenames that merely end with a known
    payload name (e.g. the stock Cursor hook before-shell-execution.js vs the
    payload execution.js) were flagged as CRITICAL. Indicator matching now
    requires a non-filename character before the match.
    
    Also add .cursor/ to the special config paths so Cursor hooks.json files
    (a known persistence vector already listed in PERSISTENCE_FILENAMES) are
    actually inspected in normal checkouts - previously they were only scanned
    by accident when the repo path happened to contain /.claude/.
    
    * test: cover underscore-prefixed filenames in IOC boundary suppression
    
    Make explicit that '_' is treated as a filename word character, so
    snake_case hook names like post_execution.js are intentionally not
    flagged by the execution.js indicator (real payload references appear
    after '/', quotes, or whitespace).
  • fix(hooks): stop pre/post Bash dispatcher from echoing the input event (#2240)
    runHooks() returned the unmodified raw stdin (the PreToolUse/PostToolUse
    input event) on stdout whenever no sub-hook produced additionalContext.
    Claude Code parses a hook's stdout as JSON and validates it against the
    hook-output schema, so echoing the input object
    ({session_id, hook_event_name, tool_name, tool_input, ...}) fails with
    "Hook JSON output validation failed — (root): Invalid input" on nearly
    every Bash command.
    
    Track whether a sub-hook deliberately set stdout (string / {stdout}, e.g.
    GateGuard) via a rawModified flag and emit '' in the pass-through case
    instead of the echoed input. Preserves GateGuard pass-through and
    block-no-verify's exit-2 blocking.
    
    Update the three dispatcher tests that codified the buggy echo behavior to
    expect empty stdout, and add a regression test for a plain pass-through
    command.
    
    Fixes #2239
    
    Co-authored-by: WOZCODE <contact@withwoz.com>
  • fix(ecc2): resolve kill_process duplicate definition on Windows (#2195)
    On Windows both cfg(windows) and cfg(not(unix)) evaluate true, so the sync taskkill kill_process and the async taskkill kill_process both compiled in and collided (E0428). Call sites are synchronous and never await it (passed as a fn pointer to enforce_session_heartbeats_with, and called as kill_process(pid)? in stop_session_recorded), so remove the stray async cfg(not(unix)) definition. The sync cfg(windows) version already handles termination via taskkill /T /F.
  • chore(deps): bump git2 from 0.20.4 to 0.21.0 in /ecc2 (#2263)
    Bumps [git2](https://github.com/rust-lang/git2-rs) from 0.20.4 to 0.21.0.
    - [Changelog](https://github.com/rust-lang/git2-rs/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/rust-lang/git2-rs/compare/git2-0.20.4...git2-0.21.0)
    
    ---
    updated-dependencies:
    - dependency-name: git2
      dependency-version: 0.21.0
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • chore(deps): bump cron from 0.12.1 to 0.16.0 in /ecc2 (#2262)
    Bumps [cron](https://github.com/zslayton/cron) from 0.12.1 to 0.16.0.
    - [Release notes](https://github.com/zslayton/cron/releases)
    - [Commits](https://github.com/zslayton/cron/commits)
    
    ---
    updated-dependencies:
    - dependency-name: cron
      dependency-version: 0.16.0
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • chore(deps): bump toml from 0.8.23 to 1.1.2+spec-1.1.0 in /ecc2 (#2261)
    Bumps [toml](https://github.com/toml-rs/toml) from 0.8.23 to 1.1.2+spec-1.1.0.
    - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.23...toml-v1.1.2)
    
    ---
    updated-dependencies:
    - dependency-name: toml
      dependency-version: 1.1.2+spec-1.1.0
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • docs: add official-sources security warning to README (#2248)
    * docs: add official-sources security warning to README
    
    Add a GFM [!WARNING] alert near the top of README.md identifying
    github.com/affaan-m/ECC and the ecc-universal / ecc-agentshield npm
    packages as the only verified distribution channels, and warning users
    that third-party re-uploads may contain malware.
    
    Closes #2242
    
    * Update README.md
    
    Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
    Co-authored-by: Affaan Mustafa <affaan.mustafa09@gmail.com>
    Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
  • fix: context-size /compact trigger, Codex marketplace plugin path, live README badges (#2237)
    - suggest-compact hook now reads the latest usage record from the session
      transcript and suggests /compact at a window-scaled token threshold
      (160k/200k window, 250k/1M window; COMPACT_CONTEXT_THRESHOLD and
      COMPACT_CONTEXT_INTERVAL overridable), re-firing per 60k-token growth
      bucket; tool-call count stays as the secondary signal (#2155)
    - Codex repo marketplace now points at ./plugins/ecc instead of ./ — Codex
      never discovers plugins whose local marketplace source.path is the
      marketplace root (verified on Codex CLI 0.137.0); plugins/ecc is a thin
      folder referencing root skills/.mcp.json per maintainer direction on
      #2097; docs flag plugin mode as experimental with the upstream blocker
      openai/codex#26037 linked (#2128)
    - README badges for installs/stars/forks now use shields endpoint badges
      backed by api.ecc.tools (live install count 3,712 vs the stale static
      150), which also eliminates shields' 'Unable to select next GitHub token
      from pool' render in the stars badge
    
    Closes #2155
    Closes #2128
  • Update plugin version and description
    Updated version to 2.0.0 and corrected skill count in description.
  • Fix version and skills count in marketplace.json
    Updated version number and corrected skills count in marketplace.json.
  • chore(deps): bump rusqlite from 0.32.1 to 0.40.1 in /ecc2 (#2211)
    * chore(deps): bump rusqlite from 0.32.1 to 0.40.1 in /ecc2
    
    Bumps [rusqlite](https://github.com/rusqlite/rusqlite) from 0.32.1 to 0.40.1.
    - [Release notes](https://github.com/rusqlite/rusqlite/releases)
    - [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
    - [Commits](https://github.com/rusqlite/rusqlite/compare/v0.32.1...v0.40.1)
    
    ---
    updated-dependencies:
    - dependency-name: rusqlite
      dependency-version: 0.40.1
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    * fix(ecc2): cast u64 columns at sqlite boundary for rusqlite 0.40
    
    rusqlite 0.40 removed the u64 ToSql/FromSql impls (SQLite stores
    INTEGER as i64). Cast token counts, durations, counts, and paging
    values to/from i64 at each bind/read site in session/store.rs.
    
    ---------
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Affaan Mustafa <me@affaanmustafa.com>
  • chore(deps): bump crossterm from 0.28.1 to 0.29.0 in /ecc2 (#2210)
    * chore(deps): bump crossterm from 0.28.1 to 0.29.0 in /ecc2
    
    Bumps [crossterm](https://github.com/crossterm-rs/crossterm) from 0.28.1 to 0.29.0.
    - [Release notes](https://github.com/crossterm-rs/crossterm/releases)
    - [Changelog](https://github.com/crossterm-rs/crossterm/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/crossterm-rs/crossterm/commits/0.29)
    
    ---
    updated-dependencies:
    - dependency-name: crossterm
      dependency-version: 0.29.0
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    * fix(ecc2): switch ratatui feature to crossterm_0_29
    
    Keep a single crossterm version in the tree after the 0.29 bump;
    with crossterm_0_28 the lockfile carried both 0.28.1 and 0.29.0.
    
    ---------
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Affaan Mustafa <me@affaanmustafa.com>
  • fix(assets): replace hero brand mark with website coral circuit mark (#2232)
    * fix(assets): replace hero brand mark with website coral circuit mark
    
    The top-left mark in the hero banner was the assets/ecc-icon.svg double-E
    lettermark, not the actual brand logo. Swap in the coral vector circuit
    mark from the ECC-website header (src/styles/brandMarks.ts), keeping the
    ~70px footprint, the soft coral glow, and every other element identical.
    PNG re-rendered at 2400x1350 via sharp with palette compression.
    
    * docs: sync skill count to 262 across catalog surfaces
    
    catalog:check was failing on main after config-gc (#2216) landed without
    a count bump. Ran npm run catalog:sync.
  • fix(ecc2): port webhook sender to ureq 3 Agent API (#2231)
    #2209 bumped ureq to 3.x but the AgentBuilder-based webhook sender
    was not ported (branch update raced the merge). ureq 3 replaces
    AgentBuilder with Agent::config_builder(); timeouts are Option-wrapped
    and status() returns http::StatusCode.
  • chore(deps): bump ureq from 2.12.1 to 3.3.0 in /ecc2 (#2209)
    Bumps [ureq](https://github.com/algesten/ureq) from 2.12.1 to 3.3.0.
    - [Changelog](https://github.com/algesten/ureq/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/algesten/ureq/compare/2.12.1...3.3.0)
    
    ---
    updated-dependencies:
    - dependency-name: ureq
      dependency-version: 3.3.0
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • docs: sync skill count to 262 after config-gc skill landed (#2230)
    npm run catalog:sync — #2216 added skills/config-gc without bumping
    documented counts, leaving catalog:check (and npm test) red on main.
  • chore(deps): bump sha2 from 0.10.9 to 0.11.0 in /ecc2 (#2208)
    * chore(deps): bump sha2 from 0.10.9 to 0.11.0 in /ecc2
    
    Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.10.9 to 0.11.0.
    - [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.9...sha2-v0.11.0)
    
    ---
    updated-dependencies:
    - dependency-name: sha2
      dependency-version: 0.11.0
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    
    * fix(ecc2): hex-encode sha2 0.11 digest output manually
    
    sha2 0.11 (digest 0.11 / hybrid-array) output arrays no longer
    implement LowerHex, so format the fingerprint bytes directly.
    
    ---------
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Affaan Mustafa <me@affaanmustafa.com>
  • docs: restore hero banner with ECC wordmark, v2.0.0 badge, and brand lettermark (#2229)
    Recreates the v1.10 hero banner design (sourced from commit 602894ef)
    that PR #2225 replaced with a plain HTML header:
    
    - Wordmark and breadcrumb now read ECC / affaan-m/ECC
    - Version badge reads v2.0.0 · Jun 2026, eyebrow updated to V2.0
    - Top-left mark is the actual assets/ecc-icon.svg lettermark (amber E,
      coral CC) instead of a generic coral square
    - Catalog columns refreshed with live counts (261 skills, 64 agents,
      84 commands, 409 catalog) and real item names from the repo
    - Harness pills updated to the current README list (Claude Code, Codex,
      Cursor, OpenCode, Gemini, Zed, Copilot)
    - SVG source committed as assets/hero.svg so future edits never need
      image archaeology; rendered to PNG at 2400x1350 via sharp
    
    README hero line restored to the markdown image; badges, sponsor table,
    and guide cards from #2225 kept intact.
  • docs(zh-CN): translate ecc-guide and parallel-execution-optimizer skills (#2217)
    * docs(zh-CN): translate ecc-guide and parallel-execution-optimizer skills
    
    Adds Simplified Chinese translations for two untranslated skills,
    following the existing docs/zh-CN/skills/ conventions (frontmatter
    name/origin preserved, code blocks and output templates kept in
    English, prose fully translated).
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    
    * docs(zh-CN): polish two phrasings per review
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
  • feat(skills): add config-gc skill (#2216)
    * feat(skills): add config-gc skill
    
    Garbage collection for Claude Code configuration sprawl: 8 scan
    channels (skills, memory, hooks, permissions, MCP, reminders,
    project history, caches), confirm-each-deletion human-in-the-loop,
    soft-delete with undo log. Subtractive counterpart to
    workspace-surface-audit and configure-ecc.
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    
    * fix(skills): address review feedback on config-gc
    
    - Replace invalid comment-out strategy for JSON permission files with
      backup + gc_log entry + jq array removal (cubic P1)
    - Swap GNU-only find -printf for portable du -k (works on macOS/BSD)
    - Capture gc date once into a variable so trash dir and undo log agree
    - Simplify shadowed-permission detection with jq index() guard
    
    Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
    
    ---------
    
    Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
  • docs(zh-CN): add Chinese translation of SKILL-DEVELOPMENT-GUIDE (#2200)
    * docs(zh-CN): add Chinese translation of SKILL-DEVELOPMENT-GUIDE
    
    Translate the comprehensive Skill Development Guide to Chinese,
    enabling Chinese-speaking contributors to learn how to create
    effective ECC skills.
    
    * fix(docs): correct all relative links in zh-CN translation
    
    Fix CONTRIBUTING.md link to zh-CN local copy, and skills links
    to point to repo-root skills/ directory instead of non-existent
    docs/skills/.
    
    ---------
    
    Co-authored-by: lege962 <1515808962@qq.com>
    Co-authored-by: legeZZZ <277193585+legeZZZ@users.noreply.github.com>
  • chore: pin rust toolchain to 1.96 for edition2024 deps (#2228)
    - add ecc2/rust-toolchain.toml pinning stable 1.96 (deps now require
      edition2024, which needs rustc 1.85+; local 1.84 could no longer build)
    - make git test fixtures hermetic: disable core.hooksPath inside temp
      repos so global identity-checking pre-push hooks cannot fail tests
  • fix: stability batch — hook stdin truncation, Codex exa TOML, Stop hook JSON, GateGuard repetition (#2227)
    * fix(hooks): fail open on oversized stdin instead of echoing truncated JSON (#2222)
    
    run-with-flags.js capped stdin at 1MB but every fallthrough path still
    echoed the truncated string to stdout. The harness parses hook stdout as
    JSON, got a document cut mid-stream, and blocked the tool call — so any
    Edit/Write with a >1MB hook payload was permanently blocked by every
    registered pre-write hook, before ECC_HOOK_PROFILE / ECC_DISABLED_HOOKS
    gating could run.
    
    - Exit 0 with empty stdout (no opinion) when the stdin cap trips, before
      any echo or gating logic.
    - Flush stdout via write callback before process.exit: exiting right
      after stdout.write() dropped everything past the ~64KB pipe buffer,
      cutting even sub-cap pass-through payloads mid-JSON.
    
    Regression tests cover the enabled, disabled, and missing-arg paths for
    oversized payloads plus full echo of sub-cap >64KB payloads.
    
    * fix(codex): stop emitting invalid exa url entry, align merge with connector policy (#2224)
    
    The Codex MCP merge declared exa with a url key, but Codex's
    [mcp_servers.*] TOML schema is stdio-only — the url key makes the
    entire config.toml fail to load, bricking both the codex CLI and the
    desktop app. Every install/update re-injected the line because the
    urlEntry branch treated the broken entry as present.
    
    - ECC_SERVERS now emits only the current default set per
      docs/MCP-CONNECTOR-POLICY.md: chrome-devtools (stdio, command/args).
      Retired servers (supabase, playwright, context7, exa, github, memory,
      sequential-thinking) are never re-emitted; existing user-managed
      entries are untouched.
    - The merge now repairs the exact ECC-emitted broken form (url-only
      exa entry) on every run so re-running the installer fixes broken
      configs instead of preserving them. User stdio exa entries
      (command + mcp-remote) are left alone.
    - check-codex-global-state.sh requires chrome-devtools instead of the
      retired set, and flags url-only exa entries with a repair hint.
    
    Tests cover repair, re-run idempotence, stdio-entry preservation, and
    no-retired-server emission in add, update, dry-run, and disabled modes.
    
    * fix(hooks): never echo truncated stdin from Stop hooks (#2090)
    
    Stop hooks follow the ECC pass-through convention (echo stdin on
    stdout), but every echoing Stop hook capped stdin and echoed the capped
    string. The Stop payload carries last_assistant_message, so a long
    final assistant message produced a JSON document cut mid-stream on
    stdout, which the harness reports as 'Stop hook error: JSON validation
    failed' across the whole Stop chain.
    
    Reproduced: a Stop payload with a >64KB last_assistant_message run
    through run-with-flags + cost-tracker emitted exactly 65536 bytes of
    invalid JSON (cost-tracker capped stdin at 64KB — far below realistic
    Stop payloads).
    
    - cost-tracker: raise the cap to 1MB (matching all other hooks) and
      suppress the pass-through echo when stdin was truncated.
    - check-console-log, stop-format-typecheck, desktop-notify: suppress
      the echo when stdin was truncated; flush stdout before process.exit
      so sub-cap payloads are not cut at the ~64KB pipe buffer.
    - All hooks keep exiting 0 (fail-open); diagnostics go to stderr.
    
    New stop-hooks-stdout test asserts the contract for every registered
    Stop hook: stdout is empty or valid JSON, exit code 0 — for realistic
    100KB payloads and oversized >1MB payloads, via the production runner
    and via direct invocation. Updated the old hooks.test.js case that
    codified the truncated-echo behavior.
    
    * fix(hooks): dampen GateGuard fact-force repetition in long sessions (#2142)
    
    In long autonomous sessions the fact-force gate produced 10+
    near-identical 'state facts -> blocked -> restate -> retry' blocks in
    one context window, which measurably raises the odds of the model
    collapsing into a degenerate single-token repetition loop.
    
    - Track a per-session fact_force_denials counter in GateGuard state
      (merged max across concurrent writers, reset with the session, robust
      to malformed on-disk values).
    - The first GATEGUARD_FACT_FORCE_FULL_DENIALS denials (default 3) keep
      the full four-fact block; later denials emit a condensed single-line
      message that carries the denial ordinal, so consecutive denials are
      structurally different and never textually identical.
    - True retries of the same target remain allowed without re-prompting
      (unchanged). Destructive-Bash and routine-Bash gates are unchanged,
      as are the ECC_GATEGUARD=off / ECC_DISABLED_HOOKS escape hatches.
    
    Eight new tests cover budget counting, condensed format, ordinal
    advancement, retry pass-through, env tuning, malformed state, MultiEdit
    dampening, and destructive-gate exemption.
    
    * fix(hooks): keep security hooks able to block on oversized stdin (#2222)
    
    Refine the truncation fail-open: instead of skipping the hook entirely,
    the runner now suppresses only its own raw-echo when stdin was
    truncated. The hook still executes and receives the truncated flag
    (run() context / ECC_HOOK_INPUT_TRUNCATED), so config-protection keeps
    blocking truncated protected-config payloads (its test requires exit 2)
    while pass-through hooks fail open with empty stdout as before.
    
    * style: apply repo formatter to touched hook files
  • docs: restore on-brand ECC header, consolidate sponsor placement, make guide links visual (#2225)
    - Replace off-brand hero PNG (wrong product name + baked version) with a
      centered HTML header using assets/ecc-icon.svg, h1, and tagline
    - Consolidate duplicated sponsor sections: polished centered sponsor table
      at top (CodeRabbit, Greptile, community sponsors, sponsor links); bottom
      section reduced to a one-liner pointing to SPONSORS.md
    - Convert guide links to visual cards using the guides' own header images,
      linked to the local guide files
    - Fix broken tmux video URL in the shortform guide to the in-repo asset
  • chore(deps): bump the cargo-minor-and-patch group (#2207)
    Bumps the cargo-minor-and-patch group in /ecc2 with 8 updates:
    
    | Package | From | To |
    | --- | --- | --- |
    | [ratatui](https://github.com/ratatui/ratatui) | `0.30.0` | `0.30.1` |
    | [tokio](https://github.com/tokio-rs/tokio) | `1.50.0` | `1.52.3` |
    | [serde_json](https://github.com/serde-rs/json) | `1.0.149` | `1.0.150` |
    | [regex](https://github.com/rust-lang/regex) | `1.12.3` | `1.12.4` |
    | [clap](https://github.com/clap-rs/clap) | `4.6.0` | `4.6.1` |
    | [libc](https://github.com/rust-lang/libc) | `0.2.183` | `0.2.186` |
    | [chrono](https://github.com/chronotope/chrono) | `0.4.44` | `0.4.45` |
    | [uuid](https://github.com/uuid-rs/uuid) | `1.22.0` | `1.23.3` |
    
    
    Updates `ratatui` from 0.30.0 to 0.30.1
    - [Release notes](https://github.com/ratatui/ratatui/releases)
    - [Changelog](https://github.com/ratatui/ratatui/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/ratatui/ratatui/compare/ratatui-v0.30.0...ratatui-v0.30.1)
    
    Updates `tokio` from 1.50.0 to 1.52.3
    - [Release notes](https://github.com/tokio-rs/tokio/releases)
    - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.50.0...tokio-1.52.3)
    
    Updates `serde_json` from 1.0.149 to 1.0.150
    - [Release notes](https://github.com/serde-rs/json/releases)
    - [Commits](https://github.com/serde-rs/json/compare/v1.0.149...v1.0.150)
    
    Updates `regex` from 1.12.3 to 1.12.4
    - [Release notes](https://github.com/rust-lang/regex/releases)
    - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/rust-lang/regex/compare/1.12.3...1.12.4)
    
    Updates `clap` from 4.6.0 to 4.6.1
    - [Release notes](https://github.com/clap-rs/clap/releases)
    - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
    - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.6.0...clap_complete-v4.6.1)
    
    Updates `libc` from 0.2.183 to 0.2.186
    - [Release notes](https://github.com/rust-lang/libc/releases)
    - [Changelog](https://github.com/rust-lang/libc/blob/0.2.186/CHANGELOG.md)
    - [Commits](https://github.com/rust-lang/libc/compare/0.2.183...0.2.186)
    
    Updates `chrono` from 0.4.44 to 0.4.45
    - [Release notes](https://github.com/chronotope/chrono/releases)
    - [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/chronotope/chrono/compare/v0.4.44...v0.4.45)
    
    Updates `uuid` from 1.22.0 to 1.23.3
    - [Release notes](https://github.com/uuid-rs/uuid/releases)
    - [Commits](https://github.com/uuid-rs/uuid/compare/v1.22.0...v1.23.3)
    
    ---
    updated-dependencies:
    - dependency-name: ratatui
      dependency-version: 0.30.1
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: cargo-minor-and-patch
    - dependency-name: tokio
      dependency-version: 1.52.3
      dependency-type: direct:production
      update-type: version-update:semver-minor
      dependency-group: cargo-minor-and-patch
    - dependency-name: serde_json
      dependency-version: 1.0.150
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: cargo-minor-and-patch
    - dependency-name: regex
      dependency-version: 1.12.4
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: cargo-minor-and-patch
    - dependency-name: clap
      dependency-version: 4.6.1
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: cargo-minor-and-patch
    - dependency-name: libc
      dependency-version: 0.2.186
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: cargo-minor-and-patch
    - dependency-name: chrono
      dependency-version: 0.4.45
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: cargo-minor-and-patch
    - dependency-name: uuid
      dependency-version: 1.23.3
      dependency-type: direct:production
      update-type: version-update:semver-minor
      dependency-group: cargo-minor-and-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • chore(deps-dev): bump the npm-minor-and-patch group across 1 directory with 2 updates (#2205)
    Bumps the npm-minor-and-patch group with 2 updates in the / directory: @opencode-ai/plugin and [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).
    
    
    Updates `@opencode-ai/plugin` from 1.15.3 to 1.16.2
    
    Updates `@types/node` from 25.7.0 to 25.9.2
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
    
    ---
    updated-dependencies:
    - dependency-name: "@opencode-ai/plugin"
      dependency-version: 1.16.2
      dependency-type: direct:development
      update-type: version-update:semver-minor
      dependency-group: npm-minor-and-patch
    - dependency-name: "@types/node"
      dependency-version: 25.9.2
      dependency-type: direct:development
      update-type: version-update:semver-minor
      dependency-group: npm-minor-and-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • chore(deps): bump actions/setup-node (#2204)
    Bumps the actions-minor-and-patch group with 1 update in the / directory: [actions/setup-node](https://github.com/actions/setup-node).
    
    
    Updates `actions/setup-node` from 6.3.0 to 6.4.0
    - [Release notes](https://github.com/actions/setup-node/releases)
    - [Commits](https://github.com/actions/setup-node/compare/53b83947a5a98c8d113130e565377fae1a50d02f...48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e)
    
    ---
    updated-dependencies:
    - dependency-name: actions/setup-node
      dependency-version: 6.4.0
      dependency-type: direct:production
      update-type: version-update:semver-minor
      dependency-group: actions-minor-and-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • feat(mcp): single-connector default set + connector policy (#2219)
    Reduce the default .mcp.json to one connector (chrome-devtools) per the
    new policy in docs/MCP-CONNECTOR-POLICY.md: a default earns its slot only
    if it is universal AND MCP beats a CLI/API wrapped in a skill. June 2026
    audit verdicts: github -> gh via github-ops skill; context7 -> REST via
    documentation-lookup; exa -> harness-native search (+ exa-search skill);
    memory -> native harness memory + instincts; playwright -> playwright CLI
    skills (vendor moved agent flows off MCP); sequential-thinking -> native
    extended thinking. All six remain opt-in in mcp-configs/mcp-servers.json.
    Tests updated: plugin-manifest policy assertions + install-apply Cursor
    expectations.
    
    Co-authored-by: ECC Test <ecc@example.test>