{"id":50493726,"url":"https://github.com/asmuelle/ai-tools-core","last_synced_at":"2026-06-02T05:03:13.281Z","repository":{"id":355860759,"uuid":"1229837299","full_name":"asmuelle/ai-tools-core","owner":"asmuelle","description":"Rust Development ai tools core","archived":false,"fork":false,"pushed_at":"2026-05-05T15:30:59.000Z","size":27,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-05T16:37:54.734Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asmuelle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-05T12:35:06.000Z","updated_at":"2026-05-05T15:31:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/asmuelle/ai-tools-core","commit_stats":null,"previous_names":["asmuelle/ai-tools-core"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/asmuelle/ai-tools-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fai-tools-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fai-tools-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fai-tools-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fai-tools-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asmuelle","download_url":"https://codeload.github.com/asmuelle/ai-tools-core/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asmuelle%2Fai-tools-core/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33806990,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-02T05:03:12.496Z","updated_at":"2026-06-02T05:03:13.265Z","avatar_url":"https://github.com/asmuelle.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ai-tools-core\n\n[![CI](https://github.com/asmuelle/ai-tools-core/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/asmuelle/ai-tools-core/actions/workflows/ci.yml)\n[![Release](https://github.com/asmuelle/ai-tools-core/actions/workflows/release.yml/badge.svg)](https://github.com/asmuelle/ai-tools-core/actions/workflows/release.yml)\n[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)\n[![Rust edition](https://img.shields.io/badge/rust-2024%20%7C%201.95%2B-orange.svg)](https://doc.rust-lang.org/edition-guide/rust-2024/index.html)\n\nShared foundation crate for the Rust AI vibe coding toolchain. Provides unified types, utilities, and configuration shared by `cargo-context`, `diff-risk`, `cargo-impact`, `spec-drift`, and `cargo-vibe`.\n\n## Why\n\nAll four tools in the toolchain reimplement the same primitives — findings, severity, location, SARIF rendering, git operations, cargo metadata parsing, secret scrubbing. `ai-tools-core` consolidates them into one dependency, ensuring consistent output formats, canonical type definitions, and a single source of truth for the `.cargo-vibe.toml` config schema.\n\n## Modules\n\n| Module | Purpose |\n|--------|---------|\n| `finding` | Unified `Finding`, `Severity` (Low/Medium/High/Critical), `Confidence` (Deterministic/Heuristic/Experimental), `Location`, `RuleId` (27 variants covering all four tools), `Attribution` |\n| `sarif` | SARIF v2.1.0 renderer. Produces GitHub Code Scanning / GitLab SAST compatible output from any `Finding` slice. |\n| `git_utils` | `changed_files()` (git diff name-only), `unified_diff()`, `blame()` (porcelain parser with Howard Hinnant civil date algorithm, zero `chrono` dependency), `is_git_repo()` |\n| `cargo_utils` | `cargo metadata` parser (`CargoMetadata`, `Package`, `Target`), `workspace_root()`, `find_rust_files()`, `is_rust_file()` |\n| `scrub` | Three-layer secret scrubbing pipeline: regex patterns (AWS keys, GitHub tokens, OpenAI keys, JWT, private keys), Shannon entropy detection, path-based file redaction. Configurable via `.cargo-context/scrub.yaml`. |\n| `config` | `.cargo-vibe.toml` parser with `VibeGlobalConfig` and per-tool `VibeToolConfig` sections. `load_project_config()` walks up from `start_dir` to find the config file. |\n\n## Types\n\n### Finding\n\nThe canonical output type across all tools:\n\n```rust\npub struct Finding {\n    pub id: String,              // stable content-hashed ID\n    pub rule: RuleId,            // which rule produced this\n    pub severity: Severity,      // Low | Medium | High | Critical\n    pub confidence: Confidence,  // Deterministic | Heuristic | Experimental\n    pub location: Location,      // file + line\n    pub message: String,         // human-readable explanation\n    pub suggested_action: Option\u003cString\u003e,\n    pub attribution: Option\u003cAttribution\u003e,  // git blame\n    pub source_tool: String,     // \"diff-risk\" | \"cargo-impact\" | \"spec-drift\"\n}\n```\n\n### Severity\n\n| Value | Weight | Marker | CI Behavior |\n|-------|--------|--------|-------------|\n| `Low` | 1.0 | 🔵 | Informational only |\n| `Medium` | 3.0 | 🟡 | Requires review |\n| `High` | 6.0 | ⚠️ | Blocks PR (with `--fail-on high`) |\n| `Critical` | 9.0 | 🚨 | Always blocks |\n\n### Confidence\n\n| Tier | Meaning | Example |\n|------|---------|---------|\n| `Deterministic` | Tool is certain | `cargo check` compile error, `diff-risk` regex match |\n| `Heuristic` | Strong signal but not proven | `cargo-impact` syn-based test reference, `spec-drift` lying test |\n| `Experimental` | LLM-backed, may hallucinate | `spec-drift` outdated logic, logic gap |\n\n### RuleId\n\n```rust\n// diff-risk\nApiContract | AsyncBoundary | SerdeDrift | AuthGate | Concurrency\n\n// spec-drift\nSymbolAbsence | ConstraintViolation | CompileFailure | DeprecatedUsage\n| LyingTest | MissingCoverage | GhostCommand | EnvMismatch\n| OutdatedLogic | LogicGap\n\n// cargo-impact\nTestReference | TraitImpl | DerivedTraitImpl | DynDispatch\n| DocDriftLink | DocDriftKeyword | FfiSignatureChange | BuildScriptChanged\n| SemverCheck | ResolvedReference | RuntimeSurface | TraitDefinitionChange\n\n// Generic\nOther\n```\n\n## Configuration\n\n### `.cargo-vibe.toml`\n\n```toml\n[vibe]\ntoken_budget = 32000\ntokenizer = \"cl100k\"\nscrub = true\nthreshold = 7.0\n\n[diff_risk]\nenabled = true\nthreshold = 8.0\nextra_args = [\"--strict\"]\n\n[cargo_impact]\nenabled = true\nextra_args = [\"--confidence-min\", \"0.7\"]\n\n[spec_drift]\nenabled = true\n\n[cargo_context]\nenabled = true\n```\n\nConfig discovery walks upward from the current directory, checking for `.cargo-vibe.toml`. Tools that have their own config files (`.cargo-context/config.yaml`, `cargo-impact.toml`, `spec-drift.toml`) continue to work; `.cargo-vibe.toml` provides overrides and a unified control surface.\n\n## Secret Scrubbing\n\nThe three-layer pipeline runs in sequence:\n\n1. **Pattern matching** — `RegexSet` of 5 built-in patterns (AWS keys, GitHub tokens, OpenAI keys, PEM private keys, JWTs). Extensible via `.cargo-context/scrub.yaml`.\n2. **Entropy detection** — Shannon entropy \u003e 4.5 on tokens ≥ 20 chars near suspicious key names.\n3. **Path redaction** — Glob patterns for files that should never be included (`.env`, `*.pem`, `*.key`).\n\nRedacted content is replaced with `\u003cREDACTED:category:rule_id:hash4\u003e` format. A `ScrubReport` tracks every redaction with rule ID, category, severity, and partial hash.\n\n## Usage\n\nAdd to your tool's `Cargo.toml`:\n\n```toml\n[dependencies]\nai-tools-core = { path = \"../ai-tools-core\" }\n```\n\n```rust\nuse ai_tools_core::{\n    finding::{Finding, Severity, Confidence, Location, RuleId},\n    sarif::SarifRenderer,\n    git_utils,\n    scrub::Scrubber,\n    config::load_project_config,\n};\n\n// Build a finding\nlet finding = Finding::new(\n    RuleId::ApiContract,\n    Severity::High,\n    Confidence::Deterministic,\n    Location::new(\"src/lib.rs\", 42),\n    \"Public API changed: fn old() -\u003e fn new()\",\n)\n.with_id(\"f-a1b2c3d4\")\n.with_tool(\"diff-risk\")\n.with_action(\"Verify all callers are updated\");\n\n// Render as SARIF\nlet renderer = SarifRenderer::new(\"my-tool\", \"0.2.0\");\nprintln!(\"{}\", renderer.render(\u0026[finding]));\n\n// Load project config\nif let Some(config) = load_project_config(\u0026std::env::current_dir().unwrap()) {\n    println!(\"Token budget: {:?}\", config.vibe.token_budget);\n}\n\n// Scrub secrets from output\nlet scrubber = Scrubber::with_builtins();\nlet (safe, report) = scrubber.scrub_with_report(\"api_key=sk-abc123...\");\nassert!(safe.contains(\"\u003cREDACTED:openai:openai_key:\"));\n```\n\n## Dependencies\n\nMinimal and carefully chosen:\n\n| Crate | Why |\n|-------|-----|\n| `serde` / `serde_json` | Type serialization, SARIF output |\n| `serde_yaml` | `.cargo-context/scrub.yaml` parsing |\n| `toml` | `.cargo-vibe.toml` config |\n| `regex` | Secret pattern matching |\n| `globset` | Path-based redaction and include/exclude |\n| `sha2` | Content hashing for stable IDs and cache keys |\n| `thiserror` | Error types |\n| `log` | Diagnostic logging |\n\n## License\n\nMIT OR Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasmuelle%2Fai-tools-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasmuelle%2Fai-tools-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasmuelle%2Fai-tools-core/lists"}