Trimmed the description from ~1216 to ~620 chars while keeping trigger coverage (reproducible cross-platform envs, system deps, local services, .flox/manifest.toml/flox activate/FloxHub).
- README: add a visible ## Security section (official sources, vuln reporting via SECURITY.md, GateGuard/IOC/AgentShield guardrails, security guide); make stats line a plain paragraph to clear MD028
- eslint: empty catch comment in run-with-flags.js; drop unneeded escape in github-coordination/parsing.js; remove unused execFileSync import in its test (#2236 follow-ups)
- markdownlint: wrap bare URLs in rules/vue/*.md (#2250 follow-up)
npm run lint green; full suite 2836/2836.
Greptile review:
- slim_dist.ps1: ErrorActionPreference SilentlyContinue -> Continue so failed
deletes are reported instead of showing a false success banner
- build_optimized.bat: wmic is removed on Windows 11 22H2+; use the built-in
%NUMBER_OF_PROCESSORS% env var (with a fallback) so --jobs is not silently 0
cubic P2: the fallback skill `python-installer-packaging` does not exist in the
repo, creating a broken routing dependency. Replace both references (description
+ When to Activate) with self-contained scoping language that keeps the
"advanced optimization only" gating without pointing at a missing skill.
Addresses PR review feedback (English description + cleaned placeholders + CI green)
and the inline bot findings.
- Add English description and canonical "When to Activate" / "How It Works" /
"Examples" sections for auto-activation; keep the existing Chinese content
- Replace the "某商业级桌面应用" placeholder with a concrete anonymized reference
("参考项目" / "生产级 PySide2 桌面应用, 323 MB")
- build_optimized.bat: compute dist size via PowerShell instead of parsing
`dir` output with the Chinese-locale string `find "个文件"` (breaks on
non-Chinese Windows)
- slim_dist.ps1: keep entry_points.txt in .dist-info (read at runtime by
importlib.metadata; deleting it breaks plugin discovery)
- Inno Setup: default the bundled VC++ redistributable to x86 to match the
recommended 32-bit build and comment out ArchitecturesInstallIn64BitMode,
with notes on switching to x64 for 64-bit builds (fixes runtime-arch mismatch)
- markdownlint: blank lines around tables (MD058)
- unicode-safety: strip emoji / U+FE0F variation selectors per repo policy
- Sync skill catalog counts 249 -> 250 across README / AGENTS / plugin /
marketplace manifests
- agent.yaml: register epic-* commands (#2236) and vue-review (#2241)
- package.json files: drop stray skills/ml-adoption-playbook entry (follows orphan-skill publish pattern; not in install-modules.json)
- unicode-safety: strip decorative emoji from dashboard-web.js (#2100) and brand-discovery refs (#2221) to pass the CI gate
- agent-compress: raise catalog token canary 5000 -> 6000 for the 67-agent catalog
Full suite green (2836/2836).
* 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
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
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).
* 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>
* 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>
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>
* 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).
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>
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.
* 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>