2166 Commits

  • feat(rules): add Vue testing rules
    Add rules/vue/testing.md:
    - Vitest + Vue Test Utils + @pinia/testing stack
    - Component mounting (mount vs shallowMount), stubs and mocks
    - Composable testing with effectScope and mountComposable helper
    - Pinia store testing pattern (setActivePinia + )
    - Vue Router testing with createMemoryHistory
    - Async assertion pitfalls (flushPromises/nextTick)
    - Testing implementation details vs rendered output
    - Coverage thresholds: 80%+ for composables/stores, smoke tests for components
    - Vitest configuration with jsdom environment and v8 coverage
  • feat(rules): add Vue architecture patterns and security rules
    Add rules/vue/patterns.md:
    - Presentational vs Container component design
    - Provide/Inject, Scoped Slots, Teleport (with 3.5+ defer prop)
    - State management decision tree and Pinia Setup Store patterns
    - Vue Router navigation guards, lazy loading, reactive route params
    - v-for/v-if patterns, v-model (Vue 3.4+ defineModel)
    - Scoped CSS (:deep, :slotted), KeepAlive with max, Dynamic Components
    - Vue 3.5+ new APIs: useId(), data-allow-mismatch, Suspense
    - Nuxt-specific patterns and Vue 2 migration notes
    
    Add rules/vue/security.md:
    - v-html XSS audit (DOMPurify sanitization checklist)
    - Unsafe URL binding validation (javascript:/data: scheme prevention)
    - Custom directive innerHTML injection
    - Secret exposure via VITE_ prefix and Nuxt runtimeConfig
    - Nuxt Nitro server API input validation with zod
    - localStorage/sessionStorage token risks, SSR browser API guards
    - target=_blank rel=noopener, CSP minimum policy
    - Prototype pollution, source maps in production
    - Vue 3.5+ SSR hydration mismatch security notes
  • feat(rules): add Vue coding-style and composables/reactivity rules
    Add rules/vue/coding-style.md:
    - <script setup> Composition API enforcement
    - Naming conventions (PascalCase components, useCamelCase composables)
    - SFC structure order, props/emits/slots patterns
    - Vue 3.5+ reactive props destructure with native default values
    - Template conventions, import ordering
    
    Add rules/vue/hooks.md:
    - ref() vs reactive() guidance and replacement pitfalls
    - Vue 3.5+ reactive props destructure (version-specific: Vue<3.5 loses reactivity, 3.5+ reactive by default with watch limitation)
    - computed() purity rules, watch vs watchEffect comparison
    - Watcher cleanup with onWatcherCleanup() (Vue 3.5+) and onCleanup callback
    - useTemplateRef() (Vue 3.5+) replacing name-matched plain refs
    - Composable conventions (use prefix, reactive returns, MaybeRef inputs)
    - shallowRef/shallowReactive for large data structures
  • feat(agents): add vue-reviewer agent for Vue.js code review
    Add vue-reviewer agent specializing in:
    - Composition API correctness and reactivity pitfalls (ref/reactive/computed/watch)
    - Vue 3.5+ reactive props destructure (stabilized, with watch limitation notes)
    - Composable patterns, template security, accessibility
    - Pinia state management, Vue Router navigation, Nuxt SSR safety
    - Vue-specific performance (shallowRef, v-memo, KeepAlive)
    
    Scope clearly delineated from typescript-reviewer for cross-invocation on .vue PRs.
  • 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
  • fix(ci): catalog sync, markdownlint, unicode safety, unsupported frontmatter key
    catalog:sync: update skill count 261→265 in README.md, AGENTS.md,
    docs/zh-CN/AGENTS.md, .claude-plugin/plugin.json
    
    markdownlint:
    - MD009: strip trailing spaces in 10_purpose-why, 20_positioning,
      40_personality-archetype, 50_voice-tone, 60_narrative-story, 90_SYNTHESIS
      (both skills/ and .agents/skills/ copies)
    - MD037: wrap ___ placeholders in backticks in 70_founder-tension.md:39
    - MD028: replace blank lines inside blockquotes with bare > in 90_SYNTHESIS.md
    
    unicode-safety: replace U+2194 (↔) with ASCII <-> in 50_voice-tone.md and
    competitive-report-structure/SKILL.md (both copies)
    
    codex-validator: remove unsupported `origin: community` key from
    brand-discovery, competitive-platform-analysis, competitive-report-structure,
    benchmark-methodology SKILL.md files (both copies)
  • fix(skills): address bot review findings post-943b299
    - competitive-platform-analysis: add ## Examples section per ECC
      guidelines (8-axis taxonomy walkthrough + pre-filter scoring matrix)
    - competitive-report-structure: clarify dimension 9 poles are client-
      specific (e.g., Memorability/Hireability) not hard-coded names
    - brand-discovery: fix terminal state — set inProgressModule to null
      after 90_SYNTHESIS.md is complete to prevent misleading resumption
    
    All fixes mirrored to .agents/ copies.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • fix(readme): restore historical skill count (261) in v2.0.0-rc.1 changelog entry
    v2.0.0-rc.1 shipped in April 2026 with 261 skills; the four new skills added
    in this PR bring the count to 265 only in v2.0.0+. Retroactively updating the
    rc.1 entry rewrote past release facts — restore the accurate historical count.
    
    Addresses cubic-dev-ai review finding (README.md:137).
  • fix(skills): address coderabbitai + cubic-dev-ai review findings
    - marketplace.json: update skill count 261 → 265
    - 90_SYNTHESIS.md (both copies): add required ## Raw / ## Synthesis
      wrappers per module contract; add Aaker brand system section (4b)
      covering archetype, identity, associations, equity (Module 40 output)
    - brand-discovery/SKILL.md: add terminal module handling for 90_SYNTHESIS
      (nextModule=null, completedModules includes 90); add path traversal
      validation rules for participant, moduleFile, outputPath in multi-founder
      mode
    - competitive-platform-analysis/SKILL.md (both copies): fix malformed
      markdown emphasis (stray * after "substitutes:")
    - competitive-report-structure/SKILL.md (both copies): clarify heatmap
      column for dimension 9 — two poles (Memorability + Hireability) must be
      represented as separate sub-columns, not averaged
    - 40_personality-archetype.md (both copies): join split heading onto one line
    - 60_narrative-story.md, 70_founder-tension.md (both copies): add trailing
      newline at EOF
    
    Duplicate .agents/ ↔ skills/ copies are intentional (Codex mirror);
    .agents/ strips `origin: community` per Codex allowlist.
  • feat(skills): add brand-discovery and competitive benchmarking pipeline
    Adds four community skills covering brand identity discovery and a
    three-skill competitive benchmarking pipeline.
    
    **brand-discovery** — Adaptive multi-session brand identity interview
    spanning 8 modules (purpose, positioning, audience, personality, voice,
    narrative, founder-brand tension, synthesis). Uses laddering, 5 Whys,
    and projective techniques. State persisted to disk via state.json so
    sessions resume across conversations without losing elicited knowledge.
    Frameworks: Sinek, Dunford, Baker, Enns, Kapferer, Aaker, Neumeier,
    Mark & Pearson, Lencioni. Includes 8 module output templates in
    references/.
    
    **competitive-platform-analysis** — Scopes and tiers a competitor set
    before benchmarking begins. Categorizes candidates along 8 generic
    creative-industry axes (positioning stance, specialization, size/model,
    engagement format, distinctiveness posture, evidence model, brand
    strength, market/reach) into Direct / Adjacent / Aspirational tiers.
    Includes a pre-filter scoring matrix. First step in the pipeline.
    
    **benchmark-methodology** — Scores each competitor across 9 weighted
    dimensions (positioning 18%, brand voice 15%, visual craft 15%, offer
    packaging 12%, evidence 12%, enterprise-readiness 10%, thought
    leadership 8%, pricing 5%, client's strategic tension 5%) with explicit
    1–5 rubrics and bias controls. Produces one profile card per competitor.
    
    **competitive-report-structure** — Assembles scored cards into a
    decision-grade report: executive summary, landscape map, competitor
    tiers, heatmap matrix, deep dives, white-space and threats, strategic
    recommendations, sources appendix.
    
    brand-discovery complements brand-voice (ECC): brand-voice extracts a
    style profile from existing source material; brand-discovery elicits
    identity from scratch through structured interviews when no prior
    material exists.
    
    A competitive set scoped without the client's positioning brief is
    noise, not intelligence — each skill enforces this by requiring the
    brief before proceeding. The 9-dimension scoring framework deliberately
    reports the client's strategic tension as two separate poles (never
    averaged) because the gap between them is the strategic finding.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • fix: guard upsertCoordinationWorkItem behind dryRun check in applySync
    The store write was unconditional, persisting work items even during dry
    runs. Move it inside the !dryRun block alongside editIssue and initialize
    snapshot to null beforehand so results.push still receives snapshot: null
    for dry runs.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • fix: enforce policy.review.required gate in applyPublish
    applyPublish was forcing review='approved' for any state that wasn't
    'changes-requested', bypassing policy.review.required entirely. Add a
    guard that throws before buildIssueStateFromAction when review approval
    is required but not yet granted.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • fix: address code-review findings in github-coordination actions
    - Remove circular validation-status check in applyValidate that prevented
      fresh claims (validation='pending') from ever reaching 'passed'
    - Add staleCoordinationLabels helper to compute coordination:* labels to
      remove on state transitions; replaces hardcoded removeLabels:[] across
      all six editIssue call sites
    - Fix duplicate label writes in applySync: syncIssueLabels already calls
      editIssue for labels, so the follow-up editIssue now only updates body
    - Skip acquireLock finding: store.acquireLock does not exist; comment
      updated to explain why the fix was not applied
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • fix: address second round of code-review findings
    actions.js:
    - Add assertValidRepo/assertValidIssueNumber guards at the top of all
      action handlers (applyClaim, applySync, applyValidate, applyPublish,
      applyReview, applyDecompose, applyUnblock) for fast-fail validation
    - applyValidate: fix status transition — set 'validated' unconditionally
      when ok=true instead of preserving 'blocked' (was inconsistent with
      projectState becoming 'ready')
    
    gh-api.js:
    - runGh: preserve GITHUB_TOKEN by default; only delete when caller
      explicitly sets options.stripGithubToken=true (was deleting by
      default, breaking CI)
    
    parsing.js:
    - extractCoordinationState: throw SyntaxError on malformed JSON instead
      of silently returning null — lets callers distinguish bad JSON from
      absent marker
    - normalizeBodyForComparison: fix regex to match JSON-quoted form
      "lastSyncAt": ... instead of bare lastSyncAt: ...
    
    policy.js:
    - loadPolicy: validate that parsed JSON is a plain object before
      spreading; coerce nested fields (labels, review, validation,
      branchModel, project, fieldNames) to objects before merging
    
    state.js:
    - assertIssueClaimable: block re-claim on status alone (not status AND
      owner) to prevent {status:'claimed', owner:null} bypass; use
      state.owner || 'unknown' in error message
    - getCoordinationState: catch SyntaxError from extractCoordinationState,
      log warning to stderr, fall back to default state
    
    tests/lib:
    - Update malformed-JSON test to expect SyntaxError throw instead of null
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • refactor: apply code-review findings to github-native coordination
    scripts/github-coordination.js:
    - parseArgs: replace 13-entry if/else chain with BOOL_FLAGS/VALUE_FLAGS
      lookup maps; shrinks from 119 to ~45 lines
    - Extract dispatchCommand(options, ctx) and formatOutput(payload, options)
      from main(); main() shrinks to ~20 lines
    
    scripts/lib/github-coordination.js:
    - Split 1041-line monolith into 6 focused sub-modules under
      scripts/lib/github-coordination/ (policy, parsing, gh-api, state,
      actions, store); index becomes a thin re-export (~55 lines)
    - Document ECC_GH_SHIM trust boundary in runGh() (gh-api.js)
    - Document applyClaim() read→check→write race condition (actions.js)
    
    tests/lib/github-coordination.test.js:
    - Refactor runTests() to data-driven DESCRIPTORS array + runGroup()
      helper; runTests() shrinks to ~10 lines
    - Add 5 new edge-case tests: normalizeRepo('') and normalizeRepo('   ')
      throw, desiredLabelsForState for blocked/ready statuses, and
      buildIssueStateFromAction for validate action (15 → 20 tests)
    
    tests/scripts/github-coordination.test.js:
    - Replace console.log in test runner with process.stdout.write
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • feat: add github-native coordination (epic-* commands + scripts + tests)
    Adds a GitHub-native coordination layer on top of ECC:
    
    Commands (7 new slash commands):
    - epic-claim, epic-sync, epic-validate, epic-publish
    - epic-review, epic-unblock, epic-decompose
    
    Scripts:
    - scripts/github-coordination.js  — CLI entry point
    - scripts/lib/github-coordination.js  — core library (state machine, gh API wrappers)
    - scripts/status.js  — coordination status reporter
    
    Config:
    - config/github-native-coordination.json  — labels, review policy, validation gates
    
    Tests:
    - tests/lib/github-coordination.test.js  — 15 unit tests for pure functions
    - tests/scripts/github-coordination.test.js  — integration/CLI test suite
    
    Registry:
    - docs/COMMAND-REGISTRY.json  — adds 7 epic-* entries, totalCommands 84 → 91
    
    No encoding changes, no prp-* modifications, no Windows shims.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • 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.
  • fix: address final lint blockers for agent self-evaluation
    - Replace U+274C cross-mark examples with ASCII FAIL: prefixes
    - Ensure agent-evaluator markdown ends with trailing newline
    - Replace markdown placeholder underscores with bracketed placeholders to satisfy markdownlint MD037
  • fix(skills): move top-level origin frontmatter key under metadata
    The official Agent Skills spec (agentskills.io/specification) whitelists exactly
    6 top-level frontmatter keys (name/description/license/compatibility/metadata/
    allowed-tools). A top-level `origin` key fails the official validator
    (anthropics/skills quick_validate.py ALLOWED_PROPERTIES; skills-ref validate).
    
    This moves `origin: X` -> `metadata.origin: X` across the canonical skills/
    tree, preserving each value verbatim. Frontmatter-only, minimal diff.
    
    - 251 SKILL.md updated (242 new metadata block, 9 appended to existing metadata)
    - origin values preserved verbatim (verified 251/251)
    - YAML validated on all changed files
    - scoped to canonical skills/ only (docs/<lang> translations + tool mirrors
      .cursor/.kiro/.agents left untouched; presumably regenerated from canonical)
    
    Addresses #2233
  • 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>
  • fix(agents): harden git commands against pager-based code execution
    Git commands (log, diff, show) can execute arbitrary code via:
    - core.pager set in repo-local .git/config
    - diff.external pointing to an attacker-controlled binary
    - filter drivers in .gitattributes
    
    Mitigation: require --no-pager flag, recommend -c core.pager=cat
    to disable pager-driven execution. Moved git commands from the
    unqualified allowlist to a hardened allowlist with explicit flags.
  • fix: address remaining review nits
    - Add top-level hooks wrapper to second JSON example (consistent with hooks.json format)
    - Extract hardcoded thresholds as module-level constants (WALL_OF_TEXT_WORDS,
      SUMMARY_CHECK_WORDS, SUMMARY_CHECK_FIRST_N, TASK_OUTPUT_RATIO_HIGH/MEDIUM)
    
    Skipped (not applicable):
    - 'Scoring defaults to 5/5' — by design for heuristic fallback; SKILL.md already
      documents pairing with LLM judge for production use
    - '--output silently ignored' — already fixed by _read_input refactor (checks
      args.output directly, not elif args.task and args.output)
  • fix(docs): clarify Stop event matcher is optional, not disallowed
    Validator (scripts/ci/validate-hooks.js line 182-184) only errors when
    matcher is missing for non-EVENTS_WITHOUT_MATCHER events. For Stop (in
    EVENTS_WITHOUT_MATCHER), matcher is optional — presence is allowed and
    validated for type correctness, absence is also accepted.
  • fix(agents): add Bash tool guardrails to agent-evaluator
    List allowed read-only commands (grep, cat, ls, find, head, tail, wc, stat,
    git log/diff/show) and explicitly forbid destructive commands (rm, mv, chmod,
    git push, git commit, sudo, pip/npm install, curl|wget piping to sh). Any
    write/delete/remote-push requires explicit user confirmation.
  • fix: address second-round review comments
    - Replace httpx.Retry references with correct httpx API usage across all files
      (httpx has no built-in Retry class; use HTTPTransport/Limits instead)
    - Fix _check_summary to check first 100 words (not 100 characters)
    - Fix template to only show → improvement arrow for non-5 scores
    - Clarify hook documentation: hook echoes reminder, does not run evaluator
    - Add return type annotation to main()
    - Make required parameter keyword-only in _read_file_or_text
  • fix: address self-evaluation review comments
    - Clarify that agent-evaluator reads skills/agent-self-evaluation/SKILL.md directly
    - Standardize on Conciseness terminology, including helper names
    - Remove invalid Stop hook matcher and avoid unsupported command-expression matcher examples
    - Add explicit hook-integration reference path in SKILL.md
    - Add summary and self-check fields to evaluate.py output, template, and agent spec
    - Refactor evaluate.py clarity and input parsing helpers
    - Remove unused task parameter from check_completeness
    
    Validation:
    - python3 -m py_compile skills/agent-self-evaluation/scripts/evaluate.py
    - evaluate.py high/low example smoke tests
    - node scripts/ci/validate-agents.js
    - node scripts/ci/validate-skills.js
    - node scripts/ci/validate-hooks.js
    - node scripts/ci/validate-no-personal-paths.js
  • fix: align report format across evaluate.py, agent spec, and template
    - evaluate.py: add CRITICAL ISSUES (axes ≤ 2) section, VERDICT line
    - agent-evaluator.md: match format_report output exactly (title, evidence markers, bar graphs)
    - templates/evaluation-report.md: match evaluate.py output format
    - All now produce identical AGENT SELF-EVALUATION REPORT structure
    
    Single authoritative format: evaluate.py's format_report() output.
  • Update agents/agent-evaluator.md
    Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • feat(skills,agents): add agent-self-evaluation skill and agent-evaluator persona
    Add structured 5-axis self-evaluation framework for agent output quality:
    - Accuracy, Completeness, Clarity, Actionability, Conciseness
    - Evidence-based scoring with concrete improvement suggestions
    - Standalone Python evaluator script with keyword heuristics
    - Detailed scoring anchors reference guide
    - High-score and low-score annotated examples
    - Reusable evaluation report template
    - Optional hook integration for session-stop evaluation
    
    Agent persona (agent-evaluator) provides a dedicated subagent
    for applying the rubric to agent output with tool-backed verification.
    
    All files tested: Python script runs, examples score correctly
    (high 4.2, low 3.4), frontmatter parses clean, 183 lines (under 500).