github agent-sh/agnix v0.12.4

latest releases: v0.18.0, v0.17.0, v0.16.6...
one month ago

Security

  • Fix minimatch ReDoS vulnerability: Added npm overrides in website/package.json to force minimatch@^10.2.1, resolving Dependabot alert #75 (ReDoS via repeated wildcards in serve-handler's transitive minimatch@3.1.2 dependency)
  • Update wasm-bindgen: Bumped wasm-bindgen from 0.2.109 (yanked) to 0.2.110 along with related crates (js-sys, web-sys, wasm-bindgen-test, etc.)

Performance

  • WASM conversion optimization: Refactored WasmDiagnostic::from_diagnostic to take ownership of Diagnostic and its fields, eliminating unnecessary string cloning when converting diagnostics to the WASM-compatible representation in agnix-wasm

Added

  • LSP pub(crate) testability refactor: Made internal modules (backend, code_actions, completion_provider, diagnostic_mapper, hover_provider, position, vscode_config) and Backend struct fields/methods pub(crate) to enable crate-internal test access. Added Backend::new_test() constructor (gated behind #[cfg(test)]) and 18 new tests in testability_tests.rs verifying that all promoted pub(crate) items are accessible from the crate root. No public API changes.
  • Improved frontmatter parsing test coverage: Added exhaustive unit tests for frontmatter_value_byte_range, frontmatter_key_offset, and frontmatter_key_line_byte_range in agnix-core. Covers unquoted/quoted values, comments, CRLF endings, indented keys, and malformed input.
  • build_lenient() on LintConfigBuilder: New builder terminal that runs security-critical glob pattern validation (syntax, path traversal, absolute paths) while skipping semantic warnings such as unknown tool names and deprecated field warnings. Intended for embedders that accept future or unknown tool names without rebuilding. ConfigError::AbsolutePathPattern variant added for absolute-path glob patterns (#475)
  • Expanded autofix coverage: Added with_fix() autofix support to 38 additional validation rules across AGM, AMP, AS, CC-AG, CC-HK, CC-PL, CC-SK, CDX, COP, CUR, GM, KIRO, MCP, OC, PE, and REF categories, bringing total fixable rules from 59 to 97 (42% of all rules)
  • Kiro steering file validation: 4 new validation rules (KIRO-001 through KIRO-004) for .kiro/steering/*.md files - validates inclusion modes (always, fileMatch, manual, auto), required companion fields, glob pattern syntax, and empty file detection
  • Cross-platform and reference validation expansion: 5 new rules - XP-007 (AGENTS.md exceeds Codex CLI 32KB byte limit), REF-003 (duplicate @import detection), REF-004 (non-markdown @import warning), PE-005 (redundant LLM instructions), PE-006 (negative instructions without positive alternatives)
  • Roo Code support: 6 new validation rules (ROO-001 through ROO-006) for .roorules, .roomodes, .rooignore, .roo/rules/*.md, .roo/rules-{slug}/*.md, and .roo/mcp.json configuration files
  • Cursor expanded coverage: Added 7 new validation rules (CUR-010 through CUR-016) for .cursor/hooks.json, .cursor/agents/**/*.md, and .cursor/environment.json, including stricter field validation and case-insensitive path detection.
  • Windsurf support: Added 4 validation rules (WS-001 through WS-004) for .windsurf/rules/*.md and .windsurf/workflows/*.md directories, plus legacy .windsurfrules detection. Includes file type detection, character limit enforcement (12,000), and empty file warnings.
  • Gemini CLI expanded coverage: Added 6 new validation rules (GM-004 through GM-009) for .gemini/settings.json hooks configuration, gemini-extension.json manifests, and .geminiignore files. Added 3 new file type detectors and validators.
  • Codex CLI expanded validation: CDX-004 (unknown config keys), CDX-005 (project_doc_max_bytes exceeds 65536 limit); updated CDX source_urls to official docs
  • OpenCode expanded validation: OC-004 (unknown config keys), OC-006 (remote instruction URL timeout warning), OC-007 (invalid agent definition), OC-008 (invalid permission configuration), OC-009 (variable substitution syntax validation)
  • agnix-wasm crate: New WebAssembly bindings for the validation engine, enabling browser-based validation without a server
  • validate_content() API: New pure function in agnix-core for validating content strings without filesystem I/O
  • filesystem feature flag: agnix-core now gates filesystem-dependent code (rayon, ignore, dirs) behind a filesystem feature (enabled by default), allowing WASM compilation with default-features = false
  • agnix-core std requirement documentation: Added crate-level documentation in lib.rs, Cargo.toml, and README.md clarifying that agnix-core requires std unconditionally and that the filesystem feature flag does not enable no_std support. Resolves downstream confusion for WASM consumers using default-features = false (#485)
  • Web playground UI polish: Teal gradient background, staggered animations, panel shadows, focus glow, SVG icons, active preset state, empty state with checkmark, loading spinner, prefers-reduced-motion support
  • Inline editor diagnostics: Red/yellow/teal wavy underlines via @codemirror/lint, gutter markers, hover tooltips with rule ID and message
  • Auto-fix in playground: WASM now exposes Fix data; per-diagnostic "Fix" buttons and "Fix all" button apply replacements directly in the editor
  • New playground presets: AGENTS.md, .claude/agents/reviewer.md, plugin.json; enriched .claude/settings.json hooks preset
  • Backend revalidation regression tests: Added coverage for did_save project-trigger revalidation and stale generation guard behavior in agnix-lsp backend tests
  • Confidence-tiered autofix engine: Fix metadata now supports confidence, alternative groups, and dependencies; CLI adds --fix-unsafe and --show-fixes; core exposes confidence-based FixApplyMode/FixApplyOptions
  • CI crate graph parity test: New workspace-level test validates that all Cargo.toml workspace members are documented in CLAUDE.md, AGENTS.md, README.md, SPEC.md, and CONTRIBUTING.md - prevents architecture-doc drift
  • resolve_validation_root file-input tests: 7 integration tests covering single-file validation mode - validates file-input path behavior, unknown file type handling, project-level rule scoping, and nonexistent file edge case (#450)
  • ImportsValidator concurrency and multi-file cycle tests: 11 new tests covering thread-safety under concurrent validation, multi-file import cycles (3- and 4-file chains), depth boundary conditions at and below MAX_IMPORT_DEPTH (complementing existing above-boundary coverage), diamond dependency graphs, and mixed valid/invalid import scenarios (#456)
  • UTF-8 boundary _checked Fix constructors: Added 6 new Fix constructor variants (replace_checked, replace_with_confidence_checked, insert_checked, insert_with_confidence_checked, delete_checked, delete_with_confidence_checked) that accept content: &str and validate UTF-8 char boundary alignment via debug_assert! in debug builds - no-ops in release builds (#463)
  • LSP concurrent revalidation stress tests: 8 new stress tests covering concurrent document open/close cycles, rapid config changes dropping stale batches, concurrent changes to the same document, config change during active validation, concurrent project and per-file validation, high document count revalidation after a single config change, concurrent hover requests during active validation, and rapid project validation generation guard behavior (#458)
  • MAX_REGEX_INPUT_SIZE precise boundary tests: 27 tests covering the exact 65536-byte limit for all 12 guarded regex functions across markdown.rs, prompt.rs, and cross_platform.rs - each function gets an at-limit (processed) and one-byte-over (rejected) test; also confirms extract_imports and extract_markdown_links are unrestricted (byte-scan/pulldown-cmark, not regex) (#457)

Changed

  • API: Removed #[non_exhaustive] from ValidationResult struct - all fields are public and the attribute was unnecessarily preventing struct literal construction and exhaustive destructuring outside the crate (#487)
  • CoreResult type alias removed (breaking): CoreResult<T> has been removed from the public API. Use LintResult<T> (i.e., Result<T, LintError>) instead. LintError is a public alias for CoreError; both remain exported. (#477)
  • __internal module feature-gated: The __internal module in agnix-core is now behind the __internal Cargo feature; it was previously unconditionally public which created semver obligations for internal items (#472)
  • normalize_line_endings promoted to stable public API: Accessible at the crate root (agnix_core::normalize_line_endings) without requiring the __internal feature (#472)
  • Project-level validation extracted to rules/project_level.rs: Extracted run_project_level_checks, join_paths, and associated unit tests from pipeline.rs into a new rules/project_level.rs module; adds 7 new unit tests for AGM-006, XP-004/005/006, and VER-001 behaviors (#474)
  • build_unchecked() scoped to test/internal use: LintConfigBuilder::build_unchecked() is now gated behind #[cfg(any(test, feature = "__internal_unchecked"))] and marked #[doc(hidden)]. External embedders should migrate to build_lenient(). The __internal_unchecked feature in agnix-core is available for integration tests that construct intentionally-invalid configs (#475)
  • Core refactor: Replaced the DEFAULTS const array in registry.rs with 8 private category ValidatorProvider structs. Public API (ValidatorRegistry, ValidatorRegistryBuilder, with_defaults()) is unchanged; this is an internal reorganization only.
  • validate_file / validate_file_with_registry return type (breaking): Both functions now return LintResult<ValidationOutcome> instead of LintResult<Vec<Diagnostic>>. ValidationOutcome is a #[non_exhaustive] enum with three variants: Success(Vec<Diagnostic>) (validation ran), IoError(FileError) (filesystem feature only - file could not be read), and Skipped (unknown file type, no validation performed). The Err path is now reserved exclusively for config-level errors. Use into_diagnostics() for a quick migration path that matches the old flat Vec<Diagnostic> behavior (#466)
  • Docs: Updated architecture references in README.md, SPEC.md, CLAUDE.md, and AGENTS.md to explicitly include the agnix-wasm workspace crate
  • Core refactor: Split oversized crates/agnix-core/src/config.rs into focused submodules (builder, rule_filter, schema, tests) while preserving the stable config API
  • LSP refactor: Split oversized crates/agnix-lsp/src/backend.rs into focused submodules (events, helpers, revalidation, tests) while preserving Backend behavior and public exports
  • named_validators() invariant documentation and debug guard: Expanded ValidatorProvider::named_validators() doc comment to document the name/factory invariant - each Some(name) must equal factory().name() or the disabled-validator mechanism silently misbehaves. Added debug_assert_eq! inside register_named() to catch mismatches early in debug builds. Added 4 tests covering the debug panic, silent-skip, and slip-through failure modes (#501)
  • Targeted #[allow(dead_code)] in parsers and schemas: Replaced blanket #![allow(dead_code)] module attributes in agnix-core parsers and schemas modules with per-item allows on the specific fields and variants that require them. Narrows lint suppression scope, making future dead-code regressions visible at the item level. No public API changes (#484)

Performance

  • ValidatorRegistry instance caching: Registry now stores pre-constructed Box<dyn Validator> instances instead of factories, eliminating per-file validator re-instantiation. validators_for() returns &[Box<dyn Validator>] (borrowed slice) instead of Vec<Box<dyn Validator>>. Added total_validator_count() method; total_factory_count() is deprecated and will be removed in a future release. The Validator trait now requires Send + Sync + 'static bounds to allow safe sharing via Arc<ValidatorRegistry> (#460)
  • REF-002 link validation: Hoisted loop-invariant canonicalize() call out of per-link loop in validate_markdown_links() - eliminates N-1 redundant filesystem syscalls when validating N markdown links
  • ValidatorRegistry memory efficiency: Replaced String with &'static str for validator names, eliminating per-validator heap allocations during registry construction. Added disable_validator_owned() variants for runtime string disabling with duplicate detection to prevent unnecessary memory leaks
  • Instruction file detection: Rewrote is_instruction_file() to use allocation-free path component iteration and eq_ignore_ascii_case, eliminating 2 heap allocations per file during project validation walks
  • Parallel validation fold: Eliminated PathBuf clone on error path in parallel fold by moving the owned value into the diagnostic
  • LSP lock-free config reads: Replaced Arc<RwLock<Arc<LintConfig>>> with Arc<ArcSwap<LintConfig>> in LSP backend, eliminating read lock contention on every did_change/did_open/did_save event (#468)
  • Disabled-validator fast path: Added named_validators() to ValidatorProvider trait (default impl wraps validators() with None names). Providers that override it with Some(name) allow ValidatorRegistryBuilder to skip the factory call entirely for disabled validators, avoiding the allocation. Built-in validators use the fast path automatically (#461)
  • LintConfig cheap cloning: Introduced Arc<ConfigData> inner struct to hold all serializable fields. Cloning a LintConfig (e.g., in validate_project / validate_project_with_registry parallel dispatch) now bumps an Arc refcount instead of deep-copying Vec<String> fields and nested structs. Mutations use Arc::make_mut for copy-on-write semantics, so the allocation only occurs when the Arc is actually shared (#467)

Fixed

  • resolve_validation_root silent fallback removed: Passing a nonexistent path to validate_project() or validate_project_with_registry() now returns Err(CoreError::Validation(ValidationError::RootNotFound { path })) immediately instead of silently falling back to the current working directory. The CLI exits with code 1 and prints "Validation root not found: <path>" to stderr. Added ValidationError::RootNotFound variant and extended CoreError::path() to cover it (#483)
  • LSP document version tracking: The LSP backend now tracks document versions reported by the client (did_open, did_change) and includes them in all publish_diagnostics calls. Editors that inspect diagnostic version tags (e.g., for stale-result suppression) now receive accurate version numbers instead of None. Version and content updates are atomized under a single lock acquisition so readers never observe a state where content and version are out of sync. Empty did_change notifications (no content changes) also correctly advance the tracked version per the LSP spec (#478)
  • Frontmatter leading newline stripped: split_frontmatter() no longer includes the newline that follows the opening --- delimiter in the extracted frontmatter string. Downstream validators (AgentValidator, AmpValidator, KiroSteeringValidator) have been updated to compute correct 1-based line numbers; diagnostic line numbers for AMP-001, CC-AG-007, and KIRO-001 through KIRO-004 are now accurate (#482)
  • Empty-frontmatter panic guard: split_frontmatter() now uses str::get() instead of direct slice indexing when extracting frontmatter content, preventing an index-out-of-bounds panic on files with an opening --- delimiter but no content (#482)
  • Predictable UUID Generation for Telemetry: Replaced the custom, insecure random number generator with a cryptographically secure pseudo-random number generator (CSPRNG) using the uuid crate. Ensures telemetry installation IDs are unpredictable and unique.
  • ImportsValidator poisoned-lock recovery: ImportsValidator now emits a lint::cache-poison Warning diagnostic (with i18n message and suggestion in en/es/zh-CN) when the shared ImportCache RwLock is poisoned by a prior validator panic, rather than panicking or silently dropping data. Validation continues with the recovered cache state. Deduplicated with push_unique_diagnostic to avoid one diagnostic per import. Includes 4 new tests covering detection, deduplication, continued import validation, and recursive-tree deduplication (#481)
  • Fix constructor range assertions: Added debug_assert!(start <= end) to Fix::replace, Fix::replace_with_confidence, Fix::delete, and Fix::delete_with_confidence to catch inverted byte ranges in debug builds (#463)
  • CRLF line ending normalization: normalize_line_endings() is now applied at all pipeline entry points (validate_file_with_type, validate_content, run_project_level_checks) and in the fix engine (apply_fixes_with_fs_options). Windows files with CRLF endings produce identical diagnostics and byte-accurate auto-fixes as their LF equivalents. Files written by --fix use LF endings (#480)
  • validate_file_with_registry disabled-validator gap: config.rules().disabled_validators was silently ignored in the validate_file_with_type path (used by validate_file_with_registry and validate_project_with_registry). Validators now respect disabled_validators at runtime in all code paths, consistent with validate_content() (#469)
  • REF-001: Corrected metadata to reflect universal applicability across all tools (not claude-code specific), changed source_type to community, and added agentskills.io reference
  • CC-HK-001: Added TeammateIdle and TaskCompleted as valid hook event names
  • CC-AG-004: Added delegate as a valid permission mode for Claude Code agents
  • CC-HK-002: Expanded PROMPT_EVENTS to include all 8 officially supported events (Stop, SubagentStop, PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, UserPromptSubmit, TaskCompleted) per Claude Code documentation, fixing false positives for prompt/agent hooks on previously-valid events
  • Playground editor not initializing: loading state was missing from CodeMirror useEffect dependency array, so the editor never mounted after WASM loaded
  • Blue flash on playground load: Changed editor pane background from --ag-code-bg to neutral --ag-surface-raised
  • Autofix dependency/group edge cases: Dependency checks now consider only structurally applicable fixes, and grouped alternatives now fall back correctly when an earlier candidate is eliminated
  • MCP-008: Updated default MCP protocol version from 2025-06-18 to 2025-11-25 to align with the latest specification
  • CC-HK-003: Downgraded from Error to Info level - matcher field is optional for tool events, not required; omitting it matches all tools (best practice hint, not an error)
  • SARIF artifact URIs: Now uses git repository root as base path instead of current working directory, ensuring correct IDE file navigation for SARIF output. Falls back to CWD when scan path is not inside a git repository (#488)
  • CI: Added defaults.run.shell: bash and set -euo pipefail to all 9 workflow files for consistent shell behavior and early error detection; GITHUB_OUTPUT redirects in release.yml are now consistently quoted (#465)
  • CI: Moved VSCE_PAT from CLI argument to environment variable in VS Code extension publish step, preventing secret exposure in process list (#464)
  • MCP server error codes: validate_file and validate_project tools now return invalid_params (JSON-RPC -32602) instead of internal_error (-32603) for user-supplied path validation failures, correctly distinguishing client errors from server faults. Renamed internal make_error helper to make_internal_error for clarity (#462)
  • MCP tools input schema: ToolsInput now uses a manual JsonSchema impl that emits anyOf with the array variant first and inline_schema = true, so MCP clients see the array-preferred anyOf directly at each property site instead of a $ref to $defs. Removed the standalone schemars 0.8 dependency; tests now use rmcp::schemars (v1) directly (#479)
  • Invalid glob pattern diagnostics: Invalid [files] glob patterns in .agnix.toml are now surfaced as Warning diagnostics (rule config::glob) in the validation output instead of writing to stderr. markdown.rs panic recovery paths also no longer write to stderr; they return empty results silently with a source comment (#459)

Don't miss a new agnix release

NewReleases is sending notifications on new releases.