Three fixes for the positive feedback loop causing runaway memory usage:
1. SIGUSR1 throttling in observe.sh: Signal observer only every 20
observations (configurable via ECC_OBSERVER_SIGNAL_EVERY_N) instead
of on every tool call. Uses a counter file to track invocations.
2. Re-entrancy guard in observer-loop.sh on_usr1(): ANALYZING flag
prevents parallel Claude analysis processes from spawning when
signals arrive while analysis is already running.
3. Cooldown + tail-based sampling in observer-loop.sh:
- 60s cooldown between analyses (ECC_OBSERVER_ANALYSIS_COOLDOWN)
- Only last 500 lines sent to LLM (ECC_OBSERVER_MAX_ANALYSIS_LINES)
instead of the entire observations file
Closes#521
The install script requires the ajv package (a devDependency) for
config validation. Without running npm install first, users get
"Cannot find module 'ajv'" when running ./install.sh.
Co-authored-by: Jeffrey Jordan <jeffreyjordan@dizplai.com>
- session-end-marker.js now exports run() function
- Enables in-process execution via run-with-flags.js
- Avoids spawnSync cross-platform issues on Windows
- Maintains backward compatibility with direct CLI execution
Fixes#429
Co-authored-by: 阳虎 <yanghu@yanghudeMacBook-Pro.local>
* feat(continuous-learning-v2): add lazy-start observer logic
Auto-starts observer when observer.enabled: true in config and no .observer.pid exists.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(continuous-learning-v2): address PR review concerns
- Use flock for atomic check-then-act to prevent race conditions
- Check both project-scoped AND global PID files before starting
- Support CLV2_CONFIG override for config file path
- Check disabled file in lazy-start logic
- Use double-check pattern after acquiring lock
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(observe.sh): address PR review comments
- Add stale PID cleanup via _CHECK_OBSERVER_RUNNING function
- Add macOS fallback using lockfile when flock unavailable
- Fix CLV2_CONFIG override: use EFFECTIVE_CONFIG for both check and read
- Use proper Python context manager (with open() as f)
- Deduplicate signaled PIDs to avoid duplicate USR1 signals
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(observe.sh): wrap macOS lockfile fallback in subshell with trap
- Wrap lockfile block in subshell so exit 0 only terminates that block
- Add trap for EXIT to clean up lock file on script interruption
- Add -l 30 (30 second expiry) to prevent permanent lock file stuck
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(observe.sh): address remaining PR review comments
- Validate PID is a positive integer before kill calls to prevent
signaling invalid targets (e.g. -1 could signal all processes)
- Pass config path via env var instead of interpolating shell variable
into Python -c string to prevent injection/breakage on special paths
- Check CLV2_CONFIG-derived directory for disabled file so disable
guard respects the same config source as lazy-start
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add Claude DevFleet multi-agent orchestration skill
Adds a skill for Claude DevFleet — a multi-agent coding platform that dispatches
Claude Code agents to work on missions in parallel, each in an isolated git worktree.
The skill teaches Claude Code how to use DevFleet's 11 MCP tools to plan projects,
dispatch agents, monitor progress, and read structured reports.
Setup: claude mcp add devfleet --transport sse http://localhost:18801/mcp/sse
Repo: https://github.com/LEC-AI/claude-devfleet
* Add DevFleet MCP config and /devfleet command
- Add devfleet entry to mcp-configs/mcp-servers.json for discovery
- Add /devfleet slash command for multi-agent orchestration workflow
* Add orchestration flow diagrams to skill and command
- Add visual flow to SKILL.md showing plan → dispatch → auto-chain → report
- Add flow to /devfleet command showing the trigger sequence
* Fix review feedback: frontmatter, workflow docs, HTTP transport
- Add YAML description frontmatter to commands/devfleet.md
- Fix manual workflow in SKILL.md to capture project_id from create_project
- Change mcp-servers.json from deprecated SSE to Streamable HTTP transport
* Address all review comments
* Add monitoring/reporting steps to full auto pattern
Addresses review feedback: the full auto example now includes polling
for completion and retrieving reports, matching the other patterns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update skills/claude-devfleet/SKILL.md
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Update skills/claude-devfleet/SKILL.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Update commands/devfleet.md
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Fix review feedback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Avdhesh Singh Chouhan <avdhesh.acro@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.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>
* feat(skills): add team-builder skill
Interactive agent picker that dynamically discovers agent markdown files,
presents a browsable domain menu, and dispatches selected agents in parallel
on a user-defined task with synthesized results.
* fix: address PR #501 review feedback
- Support both flat and subdirectory agent layouts
- Multi-path discovery with fallback probe order
- Empty-discovery fallback with helpful error message
- Enforce 5-agent cap at selection time
- Rename sections for clarity (Process → How It Works)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve PR #501 round 2 review feedback
- Fix contradictory probe-order semantics: merge-all, not first-wins
- Fix flat-layout domain extraction: frequency-based (2+ files) heuristic
- Add multi-word domain limitation note for flat layout
- Define deterministic ordering for overflow selection (alphabetical)
- Clarify TeamCreate as Claude Code tool, not undefined reference
- Shorten description frontmatter to ~60 chars
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve PR #501 round 3 review feedback
- Flat layout example now shows 2+ files per prefix (marketing, sales)
to match the documented 2+ rule
- Add filename-based fallback when agent file has no # Heading
- Add failure handling for parallel agent spawns in Step 4
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Sebastien Tang <128077249+Sabdenrog@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Patterns for catching regressions introduced by AI coding agents.
Covers sandbox/production parity testing, API response shape
verification, and integration with bug-check workflows.
Based on real-world experience where AI (Claude Code) introduced
the same bug 4 times because the same model wrote and reviewed
the code — only automated tests caught it.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Add install.ps1 PowerShell wrapper and tests
Add a Windows-native PowerShell wrapper (install.ps1) that resolves symlinks and delegates to the Node-based installer runtime. Update README with PowerShell usage examples and cross-platform npx entrypoint guidance. Point the ecc-install bin to the Node installer (scripts/install-apply.js) in package.json (and refresh package-lock), include install.ps1 in package files, and add tests: a new install-ps1.test.js and a tweak to install-sh.test.js to skip on Windows. These changes provide native Windows installer support while keeping npm-compatible cross-platform invocation.
* Improve tests for Windows HOME/USERPROFILE
Make tests more cross-platform by ensuring HOME and USERPROFILE are kept in sync and by normalizing test file paths for display.
- tests/lib/session-adapters.test.js: set USERPROFILE when temporarily setting HOME and restore previous USERPROFILE on teardown.
- tests/run-all.js: use a normalized displayPath (forward-slash separated) for logging and error messages so output is consistent across platforms.
- tests/scripts/ecc.test.js & tests/scripts/session-inspect.test.js: build envOverrides from options.env and add HOME <-> USERPROFILE fallbacks so spawned child processes receive both variables when only one is provided.
These changes prevent test failures and inconsistent logs on Windows where USERPROFILE is used instead of HOME.
* Fix Windows paths and test flakiness
Improve cross-platform behavior and test stability.
- Remove unused createLegacyInstallPlan import from install-lifecycle.js.
- Change resolveInstallConfigPath to use path.normalize(path.join(cwd, configPath)) to produce normalized relative paths.
- Tests: add toBashPath and normalizedRelativePath helpers to normalize Windows paths for bash and comparisons.
- Make cleanupTestDir retry rmSync on transient Windows errors (EPERM/EBUSY/ENOTEMPTY) with short backoff using sleepMs.
- Ensure spawned test processes receive USERPROFILE and convert repo/detect paths to bash format when invoking bash.
These changes reduce Windows-specific failures and flakiness in the test suite and tidy up a small unused import.
* feat(agents): add Rust language support — reviewer, build resolver, patterns, and testing
Add Rust-specific agents and skills following the established Go/Kotlin pattern:
- agents/rust-reviewer.md: ownership, lifetimes, unsafe audit, clippy, error handling
- agents/rust-build-resolver.md: cargo build errors, borrow checker, dependency resolution
- skills/rust-patterns/SKILL.md: idiomatic Rust patterns and best practices
- skills/rust-testing/SKILL.md: TDD, unit/integration/async/property-based testing
* fix(agents): correct Rust examples for accuracy and consistency
- unsafe fn: add inner unsafe {} block for Rust 2024 edition compliance
- edition: update from 2021 to 2024 as current default
- rstest: add missing fixture import
- mockall: add missing predicate::eq import
- concurrency: use sync_channel (bounded) and expect() over unwrap()
to align with rust-reviewer's HIGH-priority review checks
* fix(skills): correct compilation issues in Rust code examples
- collect: add .copied() for &str iterator into String
- tokio import: remove unused sleep, keep Duration
- async test: add missing Duration import
* fix(skills): move --no-fail-fast before test-binary args
--no-fail-fast is a Cargo option, not a test binary flag.
Placing it after -- forwards it to the test harness where it is
unrecognized.
* fix(agents): distinguish missing cargo-audit from real audit failures
Check if cargo-audit is installed before running it, so actual
vulnerability findings are not suppressed by the fallback message.
* fix: address automated review findings across all Rust files
- build-resolver: prefer scoped cargo update over full refresh
- testing: add Cargo.toml bench config with harness = false for criterion
- testing: condense TDD example to stay under 500-line limit
- patterns: use expect() over unwrap() on JoinHandle for consistency
- patterns: add explicit lifetime to unsafe FFI return reference
- reviewer: replace misleading "string interpolation" with concrete alternatives
* fix: align with CONTRIBUTING.md conventions
- skills: rename "When to Activate" to "When to Use" per template
- reviewer: add cargo check gate before starting review
* fix(agents): guard cargo-audit and cargo-deny with availability checks
Match the pattern used in rust-build-resolver to avoid command-not-found
errors when optional tools are not installed.
* fix: address second round of automated review findings
- testing: split TDD example into separate code blocks to avoid
duplicate fn definition in single block
- build-resolver/reviewer: use if/then/else instead of && ... ||
chaining for cargo-audit/deny to avoid masking real failures
- build-resolver: add MSRV caveat to edition upgrade guidance
* feat: add Rust slash commands for build, review, and test
Add commands/rust-build.md, commands/rust-review.md, and
commands/rust-test.md to provide consistent user entrypoints
matching the existing Go and Kotlin command patterns.
* fix(commands): improve rust-build accuracy and tone
- Restructure-first borrow fix example instead of clone-first
- Realistic cargo test output format (per-test lines, not per-file)
- Align "Parse Errors" step with actual resolver behavior
- Prefer restructuring over cloning in common errors table
* fix: address cubic-dev-ai review findings on commands
- Gate review on all automated checks, not just cargo check
- Use git diff HEAD~1 / git diff main...HEAD for PR file selection
- Fix #[must_use] guidance: Result is already must_use by type
- Remove error-masking fallback on cargo tree --duplicates
* fix: address remaining review findings across all bots
- Add rust-reviewer and rust-build-resolver to AGENTS.md registry
- Update agent count from 16 to 18
- Mark parse_config doctest as no_run (body is todo!())
- Add "How It Works" section to both Rust skills
- Replace cargo install with taiki-e/install-action in CI snippet
- Trim tarpaulin section to stay under 500-line limit
* fix(agents): align rust-reviewer invocation with command spec
- Use git diff HEAD~1 / main...HEAD instead of bare git diff
- Add cargo test as explicit step before review begins
* fix(skills): address cubic review on patterns and testing
- Remove Tokio-specific language from How It Works summary
- Add cargo-llvm-cov install note in coverage section
- Revert no_run on doctest examples (illustrative code, not compiled)
* fix(skills): use expect on thread join for consistency
Replace handle.join().unwrap() with .expect("worker thread panicked")
to match the .expect("mutex poisoned") pattern used above.
* fix(agents): gate review on all automated checks, not just cargo check
Consolidate check/clippy/fmt/test into a single gate step that
stops and reports if any fail, matching the command spec.
* fix(skills): replace unwrap with expect in channel example
Use .expect("receiver disconnected") on tx.send() for consistency
with the .expect() convention used in all other concurrency examples.
* fix: address final review round — OpenCode mirrors, counts, examples
- Add .opencode/commands/rust-{build,review,test}.md mirrors
- Add .opencode/prompts/agents/rust-{build-resolver,reviewer}.txt mirrors
- Fix AGENTS.md count to 20 (add missing kotlin agents to table)
- Fix review example: all checks pass (consistent with gate policy)
- Replace should_panic doctest with is_err() (consistent with best practices)
- Trim testing commands to stay at 500-line limit
* fix: address cubic and greptile review on OpenCode files and agents
- Fix crate::module import guidance (internal path, not Cargo.toml)
- Add cargo fmt --check to verification steps
- Fix TDD GREEN example to handle error path (validate(input)?)
- Scope .context() guidance to anyhow/eyre application code
- Update command count from 40 to 51
- Add tokio channel variants to unbounded channel warning
- Preserve JoinError context in spawned task panic message
* fix: stale command count, channel guidance, cargo tree fallback
- Fix stale command count in Project Structure section (40→51)
- Clarify unbounded channel rule: context-appropriate bounded alternatives
- Remove dead cargo tree fallback (exits 0 even with no duplicates)
- Sync OpenCode reviewer mirror with tokio channel coverage
- canonical-session: fall back to JSON file recording when the loaded
state-store module has no writer methods (factory vs instance)
- install-executor: skip node_modules and .git dirs in listFilesRecursive
to prevent ETIMEDOUT copying thousands of .opencode dependency files
- ecc.js: increase maxBuffer to 10MB for spawned subcommands to prevent
ENOBUFS on large install plan JSON output
- install-apply.test: update Cursor and Antigravity path assertions to
match flattened rule layout and remapped dirs (workflows, skills)
- ecc.test: increase maxBuffer in test runner to handle large output
- orchestrate-codex-worker.sh: guard against unreadable task file before
cat, write failure status and handoff artifacts on early exit
* feat: add SQLite state store and ECC status CLI
* fix: replace better-sqlite3 with sql.js to eliminate native module CI failures
better-sqlite3 requires native C++ compilation (node-gyp, prebuild-install)
which fails in CI across npm/pnpm on all platforms:
- npm ci: lock file out of sync with native transitive deps
- pnpm: native bindings not found at runtime
- Windows: native compilation fails entirely
sql.js is a pure JavaScript/WASM SQLite implementation with zero native
dependencies. The adapter in index.js wraps the sql.js API to match the
better-sqlite3 interface used by migrations.js and queries.js.
Key implementation detail: sql.js db.export() implicitly ends active
transactions, so the adapter defers disk writes (saveToDisk) until
after transaction commit via an inTransaction guard flag.
createStateStore is now async (sql.js requires async WASM init).
Updated status.js, sessions-cli.js, and tests accordingly.
- Registry accepts { type, value } structured targets
- Add --list-adapters and --target-type CLI flags to session-inspect
- Export adapter type from claude-history and dmux-tmux adapters
- 71 new session adapter tests, 34 new session-inspect tests
- All 1142 tests passing
* Introduces /aside — a mid-task side conversation command inspired by
Claude Code's native /btw feature. Allows users to ask a question while
Claude is actively working without losing task context or touching any files.
Key behaviors:
- Freezes current task state before answering (read-only during aside)
- Delivers answers in a consistent ASIDE / Back to task format
- Auto-resumes the active task after answering
- Handles edge cases: no question given, answer reveals a blocker,
question implies a task redirect, chained asides, ambiguous questions,
and answers that suggest code changes without making them
* Two documentation inconsistencies fixed:
* Fixed 4 pre-existing lint errors in skills/videodb/ that were causing CI to fail across all PR checks: - api-reference.md: add blockquote continuation line to fix MD028 - capture-reference.md: wrap bare URL to fix MD034 - SKILL.md: wrap bare URL to fix MD034
* feat: add project cooldown log to prevent rapid observer re-spawn
Adds session-guardian.sh, called by observer-loop.sh before each Haiku
spawn. It reads ~/.claude/observer-last-run.log and blocks the cycle if
the same project was observed within OBSERVER_INTERVAL_SECONDS (default
300s).
Prevents self-referential loops where a spawned session triggers
observe.sh, which signals the observer before the cooldown has elapsed.
Uses a mkdir-based lock for safe concurrent access across multiple
simultaneously-observed projects. Log entries use tab-delimited format
to handle paths containing spaces. Fails open on lock contention.
Config:
OBSERVER_INTERVAL_SECONDS default: 300
OBSERVER_LAST_RUN_LOG default: ~/.claude/observer-last-run.log
No external dependencies. Works on macOS, Linux, Windows (Git Bash/MSYS2).
* feat: extend session-guardian with time window and idle detection gates
Adds Gate 1 (active hours check) and Gate 3 (system idle detection) to
session-guardian.sh, building on the per-project cooldown log from PR 1.
Gate 1 — Time Window:
- OBSERVER_ACTIVE_HOURS_START/END (default 800–2300 local time)
- Uses date +%k%M with 10# prefix to avoid octal crash at midnight
- Toolless on all platforms; set both vars to 0 to disable
Gate 3 — Idle Detection:
- macOS: ioreg + awk (built-in, no deps)
- Linux: xprintidle if available, else fail open
- Windows (Git Bash/MSYS2): PowerShell GetLastInputInfo via Add-Type
- Unknown/headless: always returns 0 (fail open)
- OBSERVER_MAX_IDLE_SECONDS=0 disables gate
Fixes in this commit:
- 10# base-10 prefix prevents octal arithmetic crash on midnight minutes
containing digits 8 or 9 (e.g. 00:08 = "008" is invalid octal)
- PowerShell output piped through tr -d '\r' to strip Windows CRLF;
also uses [long] cast to avoid TickCount 32-bit overflow after 24 days
- mktemp now uses log file directory instead of TMPDIR to ensure
same-filesystem mv on Linux (atomic rename instead of copy+unlink)
- mkdir -p failure exits 0 (fail open) rather than crashing under set -e
- Numeric validation on last_spawn prevents arithmetic error on corrupt log
Gate execution order: 1 (time, ~0ms) → 2 (cooldown, ~1ms) → 3 (idle, ~50ms)
* fix: harden session guardian gates
---------
Co-authored-by: Affaan Mustafa <affaan@dcube.ai>
* fix(observe): add 5-layer automated session guard to prevent self-loop observations
observe.sh currently fires for ALL hook events including automated/programmatic
sessions: the ECC observer's own Haiku analysis runs, claude-mem observer
sessions, CI pipelines, and any other tool that spawns `claude --print`.
This causes an infinite feedback loop where automated sessions generate
observations that trigger more automated analysis, burning Haiku tokens with
no human activity.
Add a 5-layer guard block after the `disabled` check:
Layer 1: agent_id payload field — only present in subagent hooks; skip any
subagent-scoped session (always automated by definition).
Layer 2: CLAUDE_CODE_ENTRYPOINT env var — Claude Code sets this to sdk-ts,
sdk-py, sdk-cli, mcp, or remote for programmatic/SDK invocations.
Skip if any non-cli entrypoint is detected. This is universal: catches
any tool using the Anthropic SDK without requiring tool cooperation.
Layer 3: ECC_HOOK_PROFILE=minimal — existing ECC mechanism; respect it here
to suppress non-essential hooks in observer contexts.
Layer 4: ECC_SKIP_OBSERVE=1 — cooperative env var any external tool can set
before spawning automated sessions (explicit opt-out contract).
Layer 5: CWD path exclusions — skip sessions whose working directory matches
known observer-session path patterns. Configurable via
ECC_OBSERVE_SKIP_PATHS (comma-separated substrings, default:
"observer-sessions,.claude-mem").
Also fix observer-loop.sh to set ECC_SKIP_OBSERVE=1 and ECC_HOOK_PROFILE=minimal
before spawning the Haiku analysis subprocess, making the observer loop
self-aware and closing the ECC→ECC self-observation loop without needing
external coordination.
Fixes: observe.sh fires unconditionally on automated sessions (#398)
* fix(observe): address review feedback — reorder guards cheapest-first, fix empty pattern bug
Two issues flagged by Copilot and CodeRabbit in PR #399:
1. Layer ordering: the agent_id check spawns a Python subprocess but ran
before the cheap env-var checks (CLAUDE_CODE_ENTRYPOINT, ECC_HOOK_PROFILE,
ECC_SKIP_OBSERVE). Reorder to put all env-var checks first (Layers 1-3),
then the subprocess-requiring agent_id check (Layer 4). Automated sessions
that set env vars — the common case — now exit without spawning Python.
2. Empty pattern bug in Layer 5: if ECC_OBSERVE_SKIP_PATHS contains a trailing
comma or spaces after commas (e.g. "path1, path2" or "path1,"), _pattern
becomes empty or whitespace-only, and the glob *""* matches every CWD,
silently disabling all observations. Fix: trim leading/trailing whitespace
from each pattern and skip empty patterns with `continue`.
* fix: fail closed for non-cli entrypoints
---------
Co-authored-by: Affaan Mustafa <affaan@dcube.ai>