mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-18 15:54:13 +08:00
main
709 Commits
-
docs+chore: add README Security section; fix lint regressions on main
- 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.
Affaan Mustafa ·
2026-06-16 02:08:14 -04:00 -
leoeletronics ·
2026-06-16 01:59:23 -04:00 -
fix: detect destructive find -exec commands in gateguard (#2267)
* fix: detect destructive find exec commands in gateguard * chore: ignore aider local files
leoeletronics ·
2026-06-16 01:58:50 -04:00 -
chore: reconcile publish/agent surfaces after PR batch
- 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).
Affaan Mustafa ·
2026-06-15 14:21:28 -04:00 -
Merge pull request #2236 from Victor-Casado/feat/github-native-coordination
feat: add github-native coordination (epic-* commands + scripts + tests). Command registry + catalog reconciled.
Affaan Mustafa ·
2026-06-15 14:08:05 -04:00 -
Merge pull request #2241 from itkdm/feat/add-vue-ecosystem
feat: add Vue ecosystem review support (vue-reviewer agent, /vue-review command, vue-patterns skill). Duplicate rules/vue/* kept from #2250; catalog counts reconciled.
Affaan Mustafa ·
2026-06-15 14:07:31 -04:00 -
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>
cogiwimute367-create ·
2026-06-15 14:01:34 -04:00 -
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>
Mal-Qu ·
2026-06-15 14:01:29 -04:00 -
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
mehmet turac ·
2026-06-15 14:01:25 -04:00 -
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
Naomi ·
2026-06-15 14:01:21 -04:00 -
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
Md Ayan ·
2026-06-15 14:01:16 -04:00 -
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>
OrbisAI Security ·
2026-06-15 13:49:45 -04:00 -
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>@aaronjmars ·
2026-06-15 13:49:40 -04:00 -
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).
daiki75 ·
2026-06-15 13:48:50 -04:00 -
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>fiedler-itlabs ·
2026-06-15 13:48:46 -04:00 -
Bujidao ·
2026-06-12 19:44:39 +08:00 -
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
Affaan Mustafa ·
2026-06-11 16:21:53 -04:00 -
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>Victor Casado ·
2026-06-11 14:25:58 -04:00 -
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>Victor Casado ·
2026-06-11 14:05:42 -04:00 -
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>
Victor Casado ·
2026-06-11 12:58:11 -04:00 -
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
Affaan Mustafa ·
2026-06-11 00:31:33 -04:00 -
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>
Affaan Mustafa ·
2026-06-09 23:28:35 -04:00 -
release: 2.0.0 — the agent harness operating system
Graduate 2.0.0-rc.1 to stable. Bump version across package, plugin, marketplace, OpenCode, agent metadata, VERSION, and all localized docs. Add 2.0.0 release notes + README sections (en/zh/pt-BR/tr), CHANGELOG entry, and the ECC community Discord bot (dependency-free gateway client + guild command registrar). Update copilot-support and release-surface tests for the sponsored-review migration and the 2.0.0 surface.
ECC Test ·
2026-06-09 21:40:40 -04:00 -
fix: make plugin hooks run on Node 21+ and green the suite under modern Node (#2184)
ROOT CAUSE: hooks load plugin-hook-bootstrap.js via `node -e "...; process.argv.splice(1,0,s); require(s)"`. On Node 21+, require.main is `undefined` under --eval, so the `if (require.main === module)` guard was false and main() never ran — every plugin hook silently no-op'd (e.g. the MCP-health PreToolUse hook stopped blocking). CI (Node 18/20) hid this; it only surfaces on Node 21+. Fix: also run main() when require.main is undefined (the eval-bootstrap case), while staying dormant on real imports. Also clears pre-existing main debt the full local suite enforces: - catalog:sync — README/docs agent+skill counts drifted after recent merges - tests/ci/supply-chain-watch-workflow: update checkout SHA to the merged v6.0.3 (#2183) - markdownlint + check-unicode-safety --write across docs/skills Suite: 2683/2683 green under Node v25; lint + unicode clean. Co-authored-by: ECC Test <ecc@example.test>
Affaan Mustafa ·
2026-06-07 16:05:28 +08:00 -
fix(commands): resolve active plugin root in /instinct-status (#2037) (#2059)
The `/instinct-status` slash command template expanded `${CLAUDE_PLUGIN_ROOT}` directly and documented a manual-install fallback to `~/.claude/skills/continuous-learning-v2/scripts/instinct-cli.py`. When users had both an active plugin install (under `~/.claude/plugins/cache/<slug>/<org>/<version>/`) and a legacy `~/.claude/skills/continuous-learning-v2/` directory left over from a previous manual install, an empty `CLAUDE_PLUGIN_ROOT` (which Claude Code does not always populate in slash-command shell contexts) silently made the command read the stale legacy install while the active plugin hooks and observer wrote to the new XDG path. The user saw "No instincts found" while the system was actively learning — exactly the divergence the bug reporter spent hours diagnosing. Replace the brittle two-block template with the same inline resolver pattern that `hooks/hooks.json` and `/sessions` / `/skill-health` already use: env var → standard install → known plugin roots → plugin cache walk → fallback. The resolver is the canonical `INLINE_RESOLVE` constant from `scripts/lib/resolve-ecc-root.js`, so no new code is introduced — just consistent adoption of the existing pattern. Apply the same fix to all five copies of the command: - commands/instinct-status.md (canonical) - .opencode/commands/instinct-status.md - docs/zh-CN/commands/instinct-status.md - docs/ja-JP/commands/instinct-status.md - docs/tr/commands/instinct-status.md Extend tests/lib/command-plugin-root.test.js with an assertion that the canonical instinct-status.md uses the inline resolver and no longer hard-codes the legacy `~/.claude/skills/...` fallback (regression guard). zh-CN copy: polish the Chinese phrasing per LanguageTool feedback (`使用与 ... 相同的解析器` → `以与 ... 相同的解析器`) so the verb is introduced by an explicit preposition instead of reading as an awkward verb-object construction.fxdv ·
2026-06-07 13:27:05 +08:00 -
feat: Cursor-independent ECC memory via ECC_AGENT_DATA_HOME (#2066)
* feat: auto-isolate ECC memory data for Cursor via ECC_AGENT_DATA_HOME Add ECC_AGENT_DATA_HOME (defaults to ~/.claude) with Cursor-aware resolution, sessionStart env injection, install scaffolds, and hook bootstrap so memory hooks do not collide with Claude Code when both harnesses are used. Closes #2065 Co-authored-by: Cursor <cursoragent@cursor.com> * fix: log agent-data config errors and ship cursor sessionStart deps Address CodeRabbit review: log invalid .cursor/ecc-agent-data.json parse failures, and copy cursor-session-env.js plus lib deps on legacy Cursor install so sessionStart hook path exists without hooks-runtime alone. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: resolve relative agentDataHome paths from project root Project config values like ".ecc-data" now resolve against the repository root (parent of .cursor/), not process.cwd(), so Cursor hooks persist memory in the intended directory regardless of hook cwd. Addresses cubic review on PR #2066. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: explain getHomeDir duplicate and docstring policy Document why agent-data-home keeps a local home-dir helper (circular require with utils.js) and list consolidation options for maintainers. Note that CodeRabbit JSDoc coverage warnings are informational relative to ECC's usual script documentation style. Addresses cubic P2 context on PR #2066. Co-authored-by: Cursor <cursoragent@cursor.com> * test: isolate agent-data-home tests from dogfooded .cursor config Use isolated temp cwd for default-resolution cases and assert resolveAgentDataHome({ projectDir }) reads ecc-agent-data.json. Document cwd/project caveats in the test file header. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
Tom Cruise Missile ·
2026-06-07 13:27:00 +08:00 -
fix(hooks): stop false loop warnings and repeated identical context warnings (#2121)
* fix(hooks): stop false loop warnings and repeated identical context warnings Two PostToolUse monitor defects surfaced during a long single-turn session: 1. ecc-metrics-bridge hashToolCall fingerprinted Edit/Write/MultiEdit on file_path ONLY, so several distinct edits to the same file produced the same hash and tripped the loop detector ("stuck loop") even though every edit was different. Now the hash includes the edit content (old_string/new_string/content/edits) so distinct edits to one file hash differently; identical edits still collide as intended. 2. ecc-context-monitor re-emitted the SAME warning every DEBOUNCE_CALLS (5) tool calls even when nothing changed. Because the cost figure only refreshes at Stop (turn) boundaries, a single stale value printed the identical warning ~20 times within one turn. Dedupe on message content instead: a warning surfaces only when its text changes (cost moved, new file count, new loop) or on first escalation to critical, and is otherwise suppressed. Adds regression tests for the same-file/different-content hash case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(hooks): address CodeRabbit review (#2121) - ecc-context-monitor: clear dedupe state when warnings resolve, so the same warning text recurring in a later turn (context dips/recovers/dips, a loop that stops then restarts) is surfaced again instead of suppressed as a duplicate. Guarded so the no-warning hot path stays write-free. - ecc-metrics-bridge: hash the FULL serialized edit payload and truncate the digest, not the input. Slicing the serialized string to HASH_INPUT_LIMIT first could collapse large edits sharing their first 2048 chars, reviving the false-loop collision for big Write/edit payloads. - Add regression test for >2048-char edit divergence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>AHNINE Amine ·
2026-06-07 13:26:30 +08:00 -
fix: surface legacy data warning in instinct-cli status (#2127)
* fix: surface legacy data warning in instinct-cli status (#2036) When the data directory moved from ~/.claude/homunculus/ to the XDG-compliant ~/.local/share/ecc-homunculus/, legacy installs with data still in the old path saw "No instincts found" with no explanation. Add _warn_legacy_data() to cmd_status so users get a clear, actionable warning pointing them to the migration script or the CLV2_HOMUNCULUS_DIR override. Wrap the directory scan in try/except to handle permission errors gracefully. Closes #2036 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address review feedback — drop unused f-strings, resolve absolute migrate path Remove extraneous f-prefix from strings without interpolation (ruff F541). Resolve migrate-homunculus.sh path relative to instinct-cli.py instead of hard-coding a repo-relative path that only works from the repo root. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: quote migrate script path to handle spaces Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: kky <lingmu141592@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
xiaoxi ·
2026-06-07 13:26:22 +08:00 -
fix: normalize POSIX CLAUDE_PLUGIN_ROOT to Windows path in hook bootstrap (#2139)
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Matt Van Horn ·
2026-06-07 13:26:17 +08:00 -
fix(gateguard): gate force/path git checkout as destructive (#2158)
* fix(gateguard): gate force/path git checkout as destructive The destructive-command gate's `checkout` handler only flagged `git checkout -- <path>`. It missed `git checkout --force` / `-f <branch>` and `git checkout .`, all of which discard uncommitted working-tree changes, so they bypassed the gate (once the once-per-session routine-Bash gate is satisfied, they ran with no challenge). The sibling `switch` handler already covers these force forms; mirror it for `checkout`. * test(gateguard): document Test 7b force-checkout case --------- Co-authored-by: bymle <229636660+bymle@users.noreply.github.com>
bymle ·
2026-06-07 13:26:08 +08:00 -
docs(claude): install manual skills at top level (#2160)
* docs(claude): install manual skills at top level * test(docs): guard Claude manual skill install path * test(docs): detect PowerShell/$HOME nested skill-install paths Address CodeRabbit on #2160: the nested-path regression guard only matched Unix `mkdir`/`cp` with `~`, so a reintroduced PowerShell `Copy-Item ... $HOME/.claude/skills/ecc` (or backslash-separated) form would have slipped through. Extend the pattern to also cover `Copy-Item`/`New-Item` (and the `md`/`copy`/`cpi` aliases), accept `$HOME` as an alternative to `~`, allow both `/` and `\` separators, and match case-insensitively. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Kumario ·
2026-06-07 13:26:06 +08:00 -
fix: retire rules/zh from the always-loaded default rules install (#2170)
rules/zh shipped ~17KB of Chinese rule text into the auto-loaded rules tree of every default install (rules-core installs the bare 'rules' path with defaultInstall: true), with no paths: frontmatter gating. The content had also drifted behind both rules/common and the maintained translations in docs/zh-CN/rules/common (e.g. zh/coding-style.md 48 lines vs the 52-line docs/zh-CN copy), and 'zh' was already dropped from the installer's language help in favor of the gated docs-zh-cn locale module (--locale zh-CN). - move rules/zh/code-review.md to docs/zh-CN/rules/common/code-review.md: the only file with no counterpart in the maintained locale tree (fills a zh-CN parity gap with rules/common/code-review.md) - delete the remaining 10 rules/zh files, all older duplicates of docs/zh-CN/rules/common content - update trae-install test to assert the rules tree via rules/web instead Not addressed here: rules/README.md (~5.5KB of installer docs) still ships into the auto-loaded tree via the bare 'rules' module path; filtering README files from rule-tree expansion is a separate decision
konstapukarifastnetfi ·
2026-06-07 13:25:56 +08:00 -
test: skip chmod-based permission tests when running as root (#2171)
Two tests provoke EACCES via chmod (saveAliases backup double failure, appendSessionContent on a read-only file) and already skip on win32, but root ignores file modes so both fail when the suite runs as root (for example in a default Docker container). Every other chmod-based test in the repo already guards with process.getuid?.() === 0; these two were the only ones missing the guard. Apply the same skip condition and message.
konstapukarifastnetfi ·
2026-06-07 13:25:53 +08:00 -
fix: close install manifest packaging gaps (#2172)
- commands-core now ships scripts/harness-audit.js and scripts/skills-health.js: the module installs the whole commands/ dir, so /harness-audit and /skill-health were installed without their backing engines on manifest-driven installs (the original 1.10.0 failure mode) - agentic-patterns now ships scripts/claw.js: the module installs the nanoclaw-repl skill, whose workflow operates scripts/claw.js - package.json files array gains scripts/skills-health.js so the npm publish surface stays aligned with the module graph (claw.js and harness-audit.js were already listed) - orchestration drops commands/multi-workflow.md and commands/sessions.md from its explicit paths: both are already shipped by commands-core, which is a declared dependency of the module, so the duplicate ownership produced two copy operations per destination in install-state. The two scripts/lib entries are kept because hooks-runtime is NOT a declared dependency and a standalone orchestration install still needs them
konstapukarifastnetfi ·
2026-06-07 13:25:51 +08:00 -
fix(skills): keep curl credentials out of argv (#2175)
* fix(skills): avoid curl credential argv leaks * test(ci): guard secret curl examples
Kumario ·
2026-06-07 13:25:45 +08:00 -
test: guard broken-symlink tests so the suite passes on Windows (#2176)
* test: guard broken-symlink tests so the suite passes on Windows Four test cases create a dangling symlink with fs.symlinkSync() to exercise statSync catch branches, but did not guard for platforms where symlink creation is not permitted. On Windows without Developer Mode / admin rights, fs.symlinkSync throws EPERM, so these tests fail and `npm test` is red: - tests/ci/validators.test.js (Round 73, validate-commands skill entry) - tests/lib/session-manager.test.js (Round 83, getAllSessions) - tests/lib/session-manager.test.js (Round 84, getSessionById) - tests/lib/utils.test.js (Round 84, findFiles) Wrap each symlinkSync in try/catch and skip cleanly on failure, mirroring the existing convention already used in this repo (validators.test.js Round 57 and hooks/config-protection.test.js). On Linux/macOS and admin Windows the symlink still succeeds and the tests run unchanged; only the unsupported-symlink path now skips instead of failing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: only skip symlink tests on EPERM/EACCES, rethrow other errors Address CodeRabbit review: the catch blocks swallowed every error, which could mask a real test/setup failure as a false skip. Inspect err.code and only take the skip path for EPERM/EACCES (symlink creation blocked, e.g. Windows without Developer Mode); rethrow anything else so genuine failures still surface. Per the repo coding guideline: never silently swallow errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Johnson K C ·
2026-06-07 13:25:43 +08:00 -
fix(dev-server-block): stop blocking dev-<suffix> scripts (#2179)
`DEV_PATTERN`'s trailing `\b` treats a hyphen as a word boundary, so `dev\b` matched the `dev` prefix of distinct npm scripts like `dev-setup` / `dev-docs` / `dev-build` and blocked them with exit 2. Replace the trailing `\b` with `(?![\w-])` so the dev server still matches (`dev`, `dev;`, `dev:ssr`) but `dev-<suffix>` scripts pass. Adds regression tests for dev-setup/dev-docs/dev-build (allowed) and dev:ssr (still blocked). Co-authored-by: bymle <229636660+bymle@users.noreply.github.com>
bymle ·
2026-06-07 13:25:39 +08:00 -
fix(session-end): preserve $-sequences in user messages when rewriting summary (#2180)
The regenerated summary block embeds raw user-message text and was passed as the *replacement* argument to String.prototype.replace, where $-sequences ($&, $$, $`, $') are special. A user message containing $& re-injected the entire matched block (duplicating the summary markers) and $$ collapsed to $, silently corrupting the persisted session summary. buildSummarySection only escapes newlines and backticks, not $. Fix: use function replacers (() => summaryBlock) at both rewrite sites so the replacement text is treated literally. Adds an end-to-end regression test. Co-authored-by: bymle <229636660+bymle@users.noreply.github.com>
bymle ·
2026-06-07 13:25:36 +08:00 -
fix(project-detect): match packageKeys on boundaries, not substrings (#2181)
Framework detection matched a dependency against a framework's packageKeys with unbounded substring containment (dep.includes(key)), so any dependency whose name merely contained a key was misclassified: `preact` and even `reactive` were both detected as `react`. Match only when the dependency equals the key, or the key is a prefix immediately followed by a delimiter (/ . _ -). This still matches every real case (react-dom, @remix-run/node, spring-boot-starter, org.springframework.boot, github.com/labstack/echo/v4, phoenix_live_view) while excluding preact/reactive (and incidentally nextra). Adds regression tests. Co-authored-by: bymle <229636660+bymle@users.noreply.github.com>
bymle ·
2026-06-07 13:25:34 +08:00 -
fix(observer): auto-scale max_turns by analysis batch size (#2062)
* fix(observer): auto-scale max_turns by analysis batch size (#2035) The hardcoded default of MAX_TURNS=20 is insufficient when MAX_ANALYSIS_LINES=500 (also the default). Claude exhausts its turn budget before it can write all discovered instinct files, producing: Error: Reached max turns (20) Fix: when ECC_OBSERVER_MAX_TURNS is not explicitly set, compute max_turns proportionally to the actual analysis batch size: max_turns = clamp(analysis_count / 10, 20, 100) This gives: - 20–199 lines → 20 turns (existing floor, unchanged) - 500 lines → 50 turns (resolves the reported failure) - 1000 lines → 100 turns (cap) Explicitly setting ECC_OBSERVER_MAX_TURNS still overrides the auto-scaled value, preserving the existing escape hatch. * test(observer): update max_turns test for auto-scaling; document validation The max-turns budget test in tests/hooks/hooks.test.js still asserted the removed literal max_turns="${ECC_OBSERVER_MAX_TURNS:-20}", which would fail against the new auto-scaling logic. Assert the auto-scale formula and the 20/100 clamp bounds instead. Also add the explanatory comment CodeRabbit requested above the max_turns sanitization block, clarifying it guards the explicit ECC_OBSERVER_MAX_TURNS override path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
zucchini ·
2026-06-07 13:25:29 +08:00 -
fix(.cursor/hooks): route block-no-verify through local hook to fix message-body false positives (#2107) (#2177)
Cursor hooks still called `npx block-no-verify@1.1.2`, the broken external package whose matcher over-matches: it blocks legitimate `git commit` whenever `--no-verify` (or `no-verify`) appears anywhere in the command string, including inside the commit message body. The Claude Code surface already routes through the in-repo `scripts/hooks/block-no-verify.js`, which performs flag-position-aware tokenisation and passes 25 regression tests covering every false-positive case from #2107. Add a thin Cursor wrapper (`before-shell-execution-block-no-verify.js`) that reads Cursor stdin, transforms to the Claude Code `tool_input.command` shape, delegates to the local hook's exported `run()`, and forwards exit code and stderr. Update `.cursor/hooks.json` to call the wrapper instead of the npx package. New 14-case test file pins the false-positive cases from the issue plus the still-blocked real bypass attempts. Fixes #2107
Gaurav Dubey ·
2026-06-07 13:01:36 +08:00 -
fix(session-start): support ECC_SESSION_RETENTION_DAYS opt-out + document env var (#2151) (#2163)
* fix(session-start): support ECC_SESSION_RETENTION_DAYS opt-out + document env var The retention pass for *-session.tmp files (issue #2151) landed previously, but the env var that controls it was undocumented in the README and rejected falsy values (0, off, disabled), silently falling back to the 30-day default. Users who want to keep all sessions for forensic or research workflows had no way to opt out. This patch: - Extends getSessionRetentionDays() so 0|off|false|disabled|never|none disables pruning entirely (returns null sentinel; default behavior unchanged). - Updates the call site in main() to skip pruneExpiredSessions when retention is null and emits a clear "[SessionStart] Pruning disabled via ECC_SESSION_RETENTION_DAYS" log line so the operator can tell pruning is off. - Documents ECC_SESSION_RETENTION_DAYS in the README "Hook Runtime Controls" section alongside the other ECC_SESSION_* knobs. - Adds three regression tests in tests/hooks/hooks.test.js covering opt-out via 0, opt-out via off, and garbage-value fallback to default 30. Verification: - node tests/hooks/hooks.test.js — 240/240 green (incl. 3 new retention tests) - node tests/run-all.js — 2622/2622 green - npx eslint scripts/hooks/session-start.js tests/hooks/hooks.test.js — clean - node scripts/ci/validate-no-personal-paths.js — clean - node scripts/ci/check-unicode-safety.js — clean - node scripts/ci/validate-hooks.js — 28 matchers validated - node scripts/ci/validate-rules.js — 115 files validated Fixes #2151 * docs(readme): list all ECC_SESSION_RETENTION_DAYS opt-out values + add Windows example Address reviewer feedback on PR #2163: - CodeRabbit and cubic both flagged that the README docs only listed 3 of 6 opt-out values accepted by getSessionRetentionDays() (0, off, disabled), while the implementation also accepts false, never, none. - cubic also flagged the missing Windows PowerShell example for the new variable, breaking the parallel structure of the existing ECC_CONTEXT_MONITOR_COST_WARNINGS example block. Updated the README to: - Spell out all six opt-out values (0, off, false, disabled, never, none) and clarify they "keep all sessions (disable pruning)". - Add an ECC_SESSION_RETENTION_DAYS line to the Windows PowerShell example. No behavior change. README only. Verification: - npx markdownlint README.md — clean - npx eslint scripts/hooks/session-start.js tests/hooks/hooks.test.js — clean
Gaurav Dubey ·
2026-06-07 13:01:33 +08:00 -
feat(gateguard): add env knobs for routine bash gate + extra destructive patterns (#2161)
* feat(gateguard): add env knobs for routine bash gate + extra destructive patterns The JS port of gateguard-fact-force has two bash gates: a destructive gate (rm -rf, drop table, git push --force, etc.) that operators want to keep, and a once-per-session routine gate that fires on the very first bash invocation regardless of intent. Operators on hosts where the routine gate is friction without signal (Cursor, OpenCode, etc.) have been maintaining local patches that get clobbered on every plugin update; the Python upstream gateguard-ai already exposes equivalent config via .gateguard.yml. Adds two env vars, both off-by-default so existing behavior is preserved: - GATEGUARD_BASH_ROUTINE_DISABLED — truthy values (1, true, on, yes, enabled) skip the routine bash gate. Destructive gate is unaffected. - GATEGUARD_BASH_EXTRA_DESTRUCTIVE — regex source string for additional destructive patterns. Matches against the same quote-stripped, subshell-flattened command the built-in DESTRUCTIVE_SQL_DD regex sees, so a custom phrase inside $(...) or backticks is also caught. A malformed regex is logged once to stderr and treated as not configured rather than crashing the hook (hooks must never block tool execution unexpectedly). Twelve new tests pin both env vars (truthy aliases, falsy values, unset baseline, destructive-gate-still-fires, alternation members, malformed regex degrades safely, custom phrase inside command substitution). Existing 2619/2619 tests still pass; eslint clean. Fixes #2078 * fix(gateguard): reset extra-destructive warn-once gate when env value changes Both reviewers (CodeRabbit + cubic) flagged that extraDestructiveWarnLogged was never reset when GATEGUARD_BASH_EXTRA_DESTRUCTIVE flipped from one invalid regex to a different invalid regex. The sticky boolean meant a long-running process saw bad-pattern-a's warning then silently swallowed bad-pattern-b's parse failure. Fix: clear extraDestructiveWarnLogged whenever the cache key changes (i.e. before the regex compile attempt). The warn-once-per-distinct- pattern invariant now matches the per-key cache invariant. Adds a same-process regression test via loadDirectHook() that spies on process.stderr.write and asserts: same bad pattern warns once across multiple invocations; switching to a different bad pattern emits a second warning; switching to a valid regex emits zero warnings.
Gaurav Dubey ·
2026-06-07 13:01:30 +08:00 -
fix(suggest-compact): clean up old counter temp files (#2159)
* fix(suggest-compact): clean up old counter temp files claude-tool-count-<sessionId> files were written into the OS temp dir on every hook run and never removed, accumulating one orphan per session indefinitely. Sweep stale counter files at the top of main() before opening the active counter. Retention is env-tunable via COMPACT_STATE_TTL_DAYS (default 14 days); invalid values fall back to the default. The active session's counter file is preserved unconditionally even if its mtime is past the cutoff. Failures during the sweep are swallowed to preserve the always-exit-0 hook contract. Adds 7 regression tests covering the sweep, env-var validation, and the always-exit-0 invariant under a populated temp dir. Fixes #2156 * fix(suggest-compact): preserve counter files at the TTL cutoff boundary The cleanup sweep used `mtimeMs > cutoffMs` to short-circuit, which matched files whose mtime sits exactly on the cutoff boundary and deleted them. The cleanupOldCounters docstring promises only files *older than* retentionDays are removed; a file at age == retentionDays is not older than retentionDays, so it must survive. Switch the comparison to `>=` so only strictly older files fall through to deletion. Add a regression test that pins boundary-aged files (mtimeMs sitting just past the projected cutoff) are preserved. Refs #2156
Gaurav Dubey ·
2026-06-07 13:01:27 +08:00 -
fix(continuous-learning-v2): accept claude-vscode as valid entrypoint (#2134)
The observe.sh Layer 1 entrypoint guard short-circuits with exit 0 when CLAUDE_CODE_ENTRYPOINT is not in {cli, sdk-ts, claude-desktop}. Claude Code's VS Code extension sets CLAUDE_CODE_ENTRYPOINT=claude-vscode, so VS Code users see no observations recorded — observations.jsonl never gets created and the instinct pipeline stays empty. Add claude-vscode to the allowlist, mirroring the precedent in #1522 which added claude-desktop the same way. Add a regression test that spawns observe.sh under bash -x for each allowed entrypoint (cli, sdk-ts, claude-desktop, claude-vscode) and each denied entrypoint (unknown-host, claude-cody, mcp), asserting that allowed entrypoints reach Layer 2's ECC_HOOK_PROFILE check while denied entrypoints stop at Layer 1. Fixes #2102Gaurav Dubey ·
2026-06-07 13:01:24 +08:00 -
feat: worktree-lifecycle service (deterministic conflict prediction + safe GC) (#2164)
* feat: add worktree-lifecycle service (ecc.worktree-lifecycle.v1) The "unowned moat" from the orchestrator landscape research: no existing tool ships deterministic merge-conflict prediction or a safe worktree GC. - scripts/lib/worktree-lifecycle/git.js: injectable, hermetic git layer. Predicts merge conflicts WITHOUT touching the working tree via `git merge-tree`. Strips inherited GIT_* env so it is safe inside hooks. - scripts/lib/worktree-lifecycle/lifecycle.js: deterministic state machine (main/dirty/conflict/merge-ready/merged/stale/idle) + planCleanup that buckets worktrees into remove / salvage / keep. Only fully-merged trees are auto-removable; stale (unmerged+inactive) => salvage, never deleted. - scripts/worktree-lifecycle.js: CLI (--json/--conflicts/--stale/ --cleanup-plan/--base/--stale-days/--repo). - tests/lib/worktree-lifecycle.test.js: 11 tests (fake-git + real-git). Safety model mirrors the reference-arch salvage rule, validated by the 2026-06-05 MacBook->Mac Mini consolidation. Tests: 11/0. * fix: hermetic git env in session adapters + mcp-inventory lint - session adapters (codex-worktree, opencode): resolveGitBranch stripped no git env, so the "outside a repo" path returned the host branch when run inside a git hook (GIT_DIR set). Strip GIT_* before rev-parse. - mcp-inventory: fix eslint no-unused-vars (signatures) and a stale eslint-disable directive in the merged code. * test: run each test with inherited git env stripped (hermetic runner) When the suite runs inside a git hook (pre-push), git sets GIT_DIR/ GIT_WORK_TREE, which hijack 'git -C <dir>' calls in tests that exercise real git, making them operate on the host repo. Strip GIT_* before spawning each test so the suite is isolated from ambient git state. --------- Co-authored-by: ECC Test <ecc@example.test>
Affaan Mustafa ·
2026-06-07 13:00:08 +08:00 -
feat: MCP inventory (ecc.mcp.v1) — unified cross-harness MCP config view (#2146)
* feat: add MCP inventory (ecc.mcp.v1) across harnesses Read-only MCP-gateway groundwork: discover MCP server configs across every installed harness, normalize to a canonical ecc.mcp.v1 inventory, redact secrets, and report which servers are configured in 2+ harnesses (the configure-N-times pain). The read+dedup side of a unified gateway, mirroring how the session-adapter layer started read-only. Readers (per-harness config formats): - claude-code: ~/.claude.json mcpServers + project .mcp.json - codex: ~/.codex/config.toml [mcp_servers.*] TOML via @iarna/toml - opencode: ~/.config/opencode/opencode.json mcp block (command ARRAY) canonical-mcp.js: - normalize transport labels (local=>stdio, remote=>http) to stdio/http/sse - merge servers by name across harnesses; flag DRIFT when signatures differ - fragmentation report + aggregates - SECRET REDACTION: env values stripped to key names; secrets in args (--modelApiKey sk-ant-...), inline --flag=secret, and URL userinfo/token query params all redacted before storage AND before the dedup signature. scripts/mcp-inventory.js: CLI (--json, --fragmented, --help). tests/lib/mcp-inventory.test.js: 12 tests incl. a regression for the real arg-carried-secret leak found while smoke-testing on live configs. Tests: 12/0. Real-data smoke: 33 servers across 3 harnesses, 21 configured in 2+ harnesses (7 drift); secret-leak audit clean. * test: cover reader error paths, collect skip-logic, and CLI main() for mcp-inventory Lift global branch coverage past the 80% gate (was 79.86%). Adds 6 tests exercising: missing-file/malformed-JSON/missing-block reader fallbacks, codex no-parser path, collect skipping non-function readers and swallowing reader errors, CLI usage()/main() help+json+human paths, and formatHumanReport no-fragmentation + fragmented-only branches. Also scrub a real API-key fragment that had leaked into a test fixture; all secret-like fixtures are now obviously-fake FAKE... tokens. mcp-inventory.js branch 30%->93%, collect.js ->100%. Global branch 80.33%.
Affaan Mustafa ·
2026-06-06 03:55:17 +08:00 -
feat: extend session-adapter layer with codex-worktree + opencode adapters (#2145)
* feat: add codex-worktree session adapter Adds the third session adapter (after dmux-tmux and claude-history), normalizing Codex rollout sessions into the harness-neutral ecc.session.v1 snapshot. Reads ~/.codex/sessions rollout JSONL, derives objective (skipping the AGENTS.md preamble + leading message UUID), model, originator, worktree cwd, and best-effort git branch. This is step 1 of ECC-2.0-SESSION-ADAPTER-DISCOVERY (move the abstraction beyond tmux + Claude-history) and supports the wrap/adapt control-pane strategy: ECC reads sessions from any harness rather than owning one UX. - scripts/lib/session-adapters/codex-worktree.js: adapter + rollout parser - canonical-session.js: normalizeCodexWorktreeSession - registry.js: register adapter, codex/codex-worktree target types - tests/lib/session-adapters-codex.test.js: 4 tests (unit + registry routing) * feat: add opencode session adapter + allow empty intent objective Adds the fourth session adapter (after dmux-tmux, claude-history, codex-worktree), normalizing OpenCode sessions into ecc.session.v1. Reads ~/.local/share/opencode/storage: session/<project>/ses_*.json for metadata (id, directory, title, version, projectID, time) and message/<session>/msg_*.json to extract the model (modelID/providerID from the first assistant message). Derives objective from the session title, treating the auto-generated "New session - <date>" title as no objective. Recency-based active/recorded state. Schema: relax intent.objective from non-empty to allow empty string (ensureStringAllowEmpty). Sessions legitimately have no objective yet (fresh/auto-titled), and claude-history already emitted "" via metadata.title fallback. This fixes a latent over-strict validation. - scripts/lib/session-adapters/opencode.js: adapter + storage parser - canonical-session.js: normalizeOpencodeSession + ensureStringAllowEmpty - registry.js: register adapter + opencode target type - tests/lib/session-adapters-opencode.test.js: 5 tests Tests: opencode 5/0, codex 4/0, session-adapters 14/0, control-pane-state 10/0, session-inspect 8/0, control-pane 12/0. Smoke-tested on a real OpenCode session (140 messages, gpt-5.3-codex). * test: cover error/fallback branches for codex-worktree + opencode adapters Lift global branch coverage past the 80% gate (was 79.53%). Adds error and fallback path tests: missing-session/unknown-id throws, findRolloutById/ findSessionInfoById, direct file targets, objective truncation, model fallbacks, corrupt-line skip, mtime activity fallback, and the real resolveGitBranch path outside a repo. codex-worktree.js branch 52.8%->78.3%; global branch 80.04%.
Affaan Mustafa ·
2026-06-06 03:55:00 +08:00 -
feat: add dynamic workflow team orchestration surface
Adds dynamic workflow/team orchestration skills, the content pack, and control-pane work-item/Kanban state DB support. Includes reviewer hardening for state-db CLI validation, optional state DB failure handling, and mergeStateStatus projection.
Affaan Mustafa ·
2026-06-04 21:45:13 +08:00 -
feat: add ECC2 local control pane (#2131)
* feat: add ECC2 local control pane * fix: refresh control pane package locks * test: harden control pane coverage * test: allow portable control pane shutdown * test: retry local control pane fetches * fix: harden control pane error handling * fix: wrap control pane metadata
Affaan Mustafa ·
2026-06-03 21:54:30 +08:00