Releases: aliasfoxkde/aegis
Release list
v0.6.4
Aegis v0.6.4 is a release-infrastructure cut. Every platform tarball now ships the license set (LICENSE + THIRD-PARTY-NOTICES.md, generated from Cargo.lock by cargo-about), a CI lane keeps those notices fresh, and two new drift checks pin the workspace version into the fuzz lockfile and keep release metadata honest. From this tag on, release builds are reproducible: two builds of the same tag must match on every asset digest except the attestation's built_at. Also fixed: scanning a repository no longer trips over Aegis's own state directory, and 25 dead documentation links were repaired.
Added
- CI lanes for every declared-but-untested surface: the optional
tree-sitterfeature (compile + its dedicated tests), the MSRV
(rust-version 1.88 — a bump now must change the job in the same
commit), cargo-machete unused-dependency checks, and a lychee link
check over README and docs (config inlychee.toml). THIRD-PARTY-NOTICES.md, generated fromCargo.lockby the pinned
cargo-about 0.9.2 (scripts/release/generate-notices.sh; its
accepted-license list mirrorsdeny.toml). Every release tarball now
ships it alongside aegis's ownLICENSE, and anoticesCI job
regenerates and diffs the committed file so it cannot go stale
behind a dependency bump.- The workspace
repositorymetadata now points at the real public
mirror (github.com/aliasfoxkde/aegis) instead of the nonexistent
aegis/aegis. - Two CI drift checks close documented "keep in sync by hand" gaps:
scripts/check-license-parity.sh(in thenoticesjob) fails unless
deny.toml's allowed licenses andabout.toml's accepted list are
identical, andscripts/check-fuzz-lock.sh(in the Dependency Policy
job) fails whenfuzz/Cargo.lockpins anaegis-coreversion other
than the workspace's.
Fixed
- The
.aegisstate directory is now a built-in exclusion, like
node_modules,target, and.git. A baseline tracked at
.aegis/baseline.jsonquotes the findings it documents, so any scan
that included it re-flagged those contents under fingerprints naming
the baseline file — which can never appear in the baseline itself —
and every refresh compounded the artifact (one repository's baseline
grew 2,721 → 13,143 entries, ~80% self-referential). The skip applies
to directory scans, single-file scans, and--staged(which now
consults ignore rules via the newScanner::should_ignore), and it
cannot be re-included by.aegisignoreor!rules. The baseline
can now live at the conventional.aegis/baseline.jsoninside the
scanned tree with no out-of-tree dance. - 25 dead
reference:URLs shipped inside pattern definitions (and the
generated pattern docs), includingsoxlaw.com, whose domain had been
taken over and now redirects to unrelated sites; SOX patterns now
point at the official govinfo.gov text. Found by the new link-check
lane's first run (43 broken links). - Release tarballs are byte-reproducible across builders:
build.shnow
pins tar owner/group to0:0, normalizes member modes, sets every
member's mtime to the tag's commit time, and gzips with-n, so the
digests no longer depend on which uid/gid or clock ran the build.
Found by the v0.6.3 cross-check, where two independent builds of the
same tag produced byte-identical binaries but differing tarball
digests. - The release builder image is pinned to
rust:1.88-bookworm(matching
the runtime image) instead of floatingrust:1-bookworm, and every
GitHub Actions ref — including the@nightlytoolchain ref and the
bench cache/artifact actions — is now SHA-pinned.
Known issue (fixed forward): this tag's tarballs record an
INT64_MINmember mtime instead of the tag's commit time —build.shread%ctfrom the annotated tag, whose display is multi-line, and tar silently substituted a garbage date. Extraction is unaffected (GNU tar, busybox tar, python tarfile verified) and digests are stable. The fix (read from the commit + reject a non-numeric epoch) lands in #157.
v0.6.3
Added
aegis-mcpnow speaks the Model Context Protocol lifecycle:
initialize(version negotiation across 2024-11-05, 2025-03-26, and
2025-06-18),notifications/initialized,tools/list(all seven
scanning tools with JSON-Schema input schemas),tools/call(results
as text content; tool failures asisError: trueresults), and
ping. Generic MCP clients such as Claude Desktop can now use the
server without a translation shim; the original custom JSON-RPC
method set is unchanged and dispatches to the same implementations.- Wire-conformance fixture suites replayed against the real binaries
pin both integration surfaces:aegis-mcp's stdio handshake,
discovery, sandbox rejection, unknown-tool, and parse-error semantics
(crates/aegis-mcp/tests/fixtures/), andaegis-daemon's
Unix-socket JSON-lines protocol — error envelopes, sandbox refusal
without content leakage, blank-line framing, and scan receipts
(crates/aegis-daemon/tests/fixtures/). - The corpus harness now measures per rule, not just in aggregate: any
rule with enough corpus observations must hold a per-rule precision
floor (0.80 at ≥ 2 observations), and hand-assignedconfidence
labels are calibrated against measured precision demote-only
(high≥ 0.95,medium≥ 0.80 at ≥ 3 observations — the gate can
force a label down or a regex fix, never a promotion). A new
tests/corpus/negative/section pins the 2026-09-22 false-positive
audit: each fixed rule (hipaa-phi, mesa-optimization,
k8s-run-as-non-root, code-injection-request, executable-file-upload)
keeps a regression fixture where it must stay silent, preserving the
shape that made the old regex fire. aegis-core::clonenow detects Type-3 (near-miss) clones —
copy-paste with reordered or inserted statements — instead of only
labelling them. Similarity is a longest-common-subsequence ratio over
the two blocks' token sequences (identifiers and literals compared by
role), scored on the best-aligned of a block stride's window phases,
so order and multiplicity count; the previous bag-of-tokens score
ignored both and rated unrelated same-shape functions as Type-1 at
1.0. Blocks grew from 20 to 40 tokens because a near-miss claim
cannot rest on a statement and a half of role-normalized code, so
regions shorter than 40 tokens are no longer compared, overlapping
windows are no longer compared with each other, a file yielding more
than 256 windows is sampled rather than paired in full, and reported
clone locations carry real line numbers (they were always line 1).- Clone detection is wired into the CLI:
aegis scan --detect-clones
runs the detector on every analyzed file and reports the pairs in a
Code clonessection of the human output and understats.clonesin
JSON output (kind, description, similarity, token count, and the two
locations with real line numbers). Clones are a separate output
channel, not findings: they never enter the finding list, risk score,
SARIF document, or exit code, and default scans serialize
byte-identical JSON to previous releases. Aclone_detection
criterion bench feeds the weekly trend.
Security
- Both wire servers now cap request frames at 10 MiB. Previously a
single authorized peer could exhaust server memory with one
arbitrarily long line (read_line/next_linegrow without limit).
aegis-mcpanswers an oversized line with JSON-RPC-32600and ends
the session;aegis-daemonanswers once with a size error and drops
the connection while continuing to serve other clients.
Changed
- The workspace denies
clippy::unwrap_used,clippy::expect_used, and
clippy::panicin production code: errors must be values. The 29
unwrap()/expect()call sites the gate surfaced were removed — 27
by converting internal lock state toparking_lot, which does not
poison and so needs no unwrap-on-lock idiom, and 2 by propagating the
error properly — and the 3 deliberate exceptions (a compile-time
constant regex, epoch arithmetic, a documented panicking convenience
constructor) carry an inline#[allow]naming the invariant it
protects. Test code is exempt throughclippy.toml's
allow-…-in-testsflags. - A new
[lints.rustdoc]table denies broken and private intra-doc
links, and CI gains aRustdocjob that runscargo docwith
RUSTDOCFLAGS=-D warningsso the gate is actually exercised. - The bounded newline framing shared by both wire servers lives in one
place:aegis-core::transport(read_bounded_line,FrameRead,
MAX_FRAME_BYTES) is now the single implementation behind the MCP
stdio server and the daemon socket server, which previously carried
byte-identical copies plus duplicate test suites. -c/--configresolution is deterministic: a value with a path
separator or a.jsonextension is a file path (a typo'd path now
fails with the real I/O error instead of the preset list); a bare
name is always a preset, even if the working directory happens to
contain a file with that name..aegis.ymlloading probes the scan root once: callers that already
located the file useload_user_pattern_definitions_from_path
instead of re-running the directory probe inside
load_user_pattern_definitions.- The daemon's
list_patternsno longer builds a JSON description of
every pattern only to throw it away; it reports the registry count,
which is what the daemon protocol documents. Full pattern metadata
remains the MCP server'slist_patternsresponse. - The CLI's internal scan dispatcher refuses
--stdinwith an
explicit error instead of silently scanning a decoy empty string;
real stdin content flows through the async entry point, which is
unchanged. - A coverage floor now actually gates: the Codecov upload has been
failing on every run for lack of a token, socodecov.yml's targets
were never evaluated. The Coverage job computes a native floor from
the lcov report withscripts/coverage-floor.sh— 97.0% lines
against the CI-measured 97.61% over the counted set (2026-09-24),
ignoringcrates/aegis-wasmand the root shim binary exactly like
codecov.yml, whose project target is synced. The gate logs a
per-crate breakdown of what it counted; the floor ratchets up, never
down to pass.
Removed
- Dead
Scannerstate and config surface that no shipped binary could
observe: the never-readsuppression_managerfield (the scan path
already builds its own), theConfigfieldsstrict_mode,
performance_mode,exit_on_findings,max_file_size_mb,
binary_file_detection,gitignore_respect,aegisignore_respect,
andtimeout_seconds, and theStrictMode/PerformanceModeenums
only those fields carried. Three of the fields were applied in
exactly one place,Scanner::from_config, which no binary in this
workspace calls — the CLI builds scanners from flags instead — so a
gitignore_respect: falsein a profile never actually disabled
ignore handling anywhere; keeping parse-but-ignore fields was the
lie. Existing user profiles still load because serde skips unknown
keys by default. The deadis_path_dangerous/get_sandbox_root
sandbox helpers are gone too. - The
DEFAULT_CATEGORIESconstant,Pattern::regex_matcheshelper,
and the unusedparse_sourceAST wrapper — all unreferenced.
Fixed
- Pattern-finding columns are now 1-indexed within the match's own line.
They previously carried the byte offset within the whole file, so
file.rs:42:18513-style locations could not be opened in an editor and
SARIFstartColumnvalues were meaningless on anything but tiny files.
fingerprint(the baseline key) never included the column, so existing
baselines still match;stable_idvalues change because the column is
part of their material. env-file-in-gitmatched a.envpath at a line start by consuming the
preceding newline character, which attributed the finding to the previous
line — where anaegis:ignore:env-file-in-gitdirective does not sit —
so a deliberately committed-and-suppressed.envmention in
docker/.dockerignorestill failed the scan. The rule now uses^in
multiline mode for the line-boundary case, so the match starts at the
.envitself and inline suppression works.- An unrecognized
--severity-thresholdvalue (or theseverity_threshold
key of a-cprofile) silently disabled the severity filter — a typo
likehihgreported more findings than requested at exit code 1,
with no diagnostic. The value is now validated the way--categories
and the anomaly allow-list always were: the CLI rejects it before any
scan mode runs (including--env/--stdin/--diff), and the
aegis-corescan entry points return
ScanError::InvalidOptions;ScanOptions::validateoffers the same
check to library callers. - Clone reports are bounded: pairing stops at 256 clone pairs per file
(MAX_REPORTED_CLONES), so a minified or generated file where nearly
every window pair qualifies can neither flood the report with a
multi-gigabytestats.cloneslist nor pay for the rest of the
quadratic pairing pass behind it. Previously the per-file pair count
was unbounded (up to 32,640 with a full block grid). - A clone-detector failure on a file is now recorded in the inspection
ledger (<path>#clones, statusFailed) instead of only being
logged, so a failed pass cannot masquerade as "no clones found" in
SARIF run properties and receipts. - Anchored ignore rules (
.aegisignore/.gitignore) now match when
the scan root is absolute: rules are evaluated against the path
relative to the configured root, so"docs/files/js/"fires on
walker paths like/workspace/docs/files/js/mock.jswhere it
previously silently never matched. Path separators are normalized to
/before matching, which also makes these rules work on Windows
(strip_prefix...
v0.6.2
Aegis 0.6.2 — honesty pass. Five false-positive-prone detection rules
regex-corrected (hipaa-phi, code-injection-request, mesa-optimization,
executable-file-upload direction, k8s-run-as-non-root inversion), the
repository self-scans clean at high severity, enable/disable now
persist, worker count actually sizes the scan pool, and the never-wired
output pipeline (fake PostgreSQL/MySQL handlers) is gone. The Docker
image builds and was verified end-to-end; Kubernetes usage is a scan
CronJob. CI pins --locked everywhere and the release attestation
records the lockfile SHA-256.
Removed
- The never-wired
output-pipelinefeature ofaegis-core(file,
SQLite, webhook, PostgreSQL, and MySQL outputs plus the parallel YAML
preset configuration world). The PostgreSQL and MySQL implementations
logged what they "would insert" and returned success — fake
implementations — and no binary consumed any of it. Code that needs
database sinks should callserde_jsonand its own client.
Fixed
aegis disable <pattern>/aegis enable <pattern>now persist to
<config dir>/aegis/pattern-state.jsonand are honored by scans and
aegis list; previously both subcommands printed a confirmation and
changed nothing. Unknown pattern names fail loud with the valid-name
hint. Integration tests run against an isolatedXDG_CONFIG_HOME.ScanOptions::workersnow actually sizes the scan thread pool (rayon's
global pool ignored it), pool-build failures warn and fall back once,
andworkers_usedmerges as a maximum across shard stats instead of
being lost.- Silent-failure paths: an unscannable pattern is logged with its name
instead of vanishing from scans; the clone tokenizer advances by
UTF-8 width instead of one byte (panicked on multibyte escapes);
trim_stringtruncates on character boundaries; MCP and daemon
response writes surface transport errors instead of.ok()-ing them.
Security
- Container/deploy hardening: the Docker image now builds (rust 1.88,
--locked, non-root) and the Kubernetes phantom HTTP daemon
(endpoints that never existed) was replaced by a scan CronJob with no
Kubernetes API access.
v0.6.1
Aegis 0.6.1 sharpens two detectors and rebuilds the release pipeline on
GitForge. The Dockerfile secret detector now anchors its matches to actual
Dockerfile directives, and the CI-bypass detector gained precision fixes that
cut false positives on legitimate workflow files. The release process itself
changed: every asset — five platform tarballs, the WASM module, source
archives, checksums, and a new build attestation — is built by the GitForge
pipeline and mirrored to this release, with checksums.txt now covering the
complete published set. Release titles are the bare version tag.
Changed
- Releases are built by the GitForge pipeline (
.gitforce.yml) and synced
to the GitHub release byscripts/release/publish.sh; the GitHub
Releaseworkflow remains as a manual-dispatch fallback running the same
scripts. Every release now shipsattestation.json
(aegis.release-attestation/v1) recording the tag, commit, builder
platform, toolchains, and the SHA-256 of every other asset, and the WASM
asset is published asaegis-wasm.wasm— previously the crate-mangled
aegis_wasm.wasm— to match theaegis-<target>naming of the platform
archives. Release titles are the bare tag. darwin binaries are
cross-linked with zig on the build host rather than built on Apple
hardware; the attestation states this instead of hiding it.
Fixed
- The
secrets-in-dockerfilerule is anchored to line-oriented Dockerfile
directives —^\s*(ARG|ENV)\s+…under multiline matching, where it
previously matchedARG/ENVand a secret-ish word anywhere in a file —
so Rust, Markdown, and test prose containing words likeENVorTOKEN
are no longer reported as Dockerfile secrets. - The
ci-bypassrule now requires explicit bypass syntax (--no-verify,
continue-on-error: true, or a direct verb–target pairing such as
skip tests) and fires only in CI, configuration, and shell file types,
instead of flagging any line of prose where a bypass-like word appears
near a CI-like one.
v0.6.0
Ten PHI-handling rules for HIPAA technical safeguards in healthcare, per-language anomaly baselines, and a configurable anomaly layer (--no-anomalies, --anomaly-detectors, config profiles). checksums.txt is now a verifiable sha256sum -c manifest of the published archives.
Changelog
Added
- Ten PHI-handling rules in
healthcare, which previously only held
identifier-format detectors: three more provider identifiers (NPI,
DEA registration, Medicare MBI/HICN) plus seven HIPAA
technical-safeguard hazards — PHI in log or print output, hard-coded
patient-identifier literals, patient resources referenced over
plaintext HTTP, PHI routed through email,SELECT *over PHI tables
(the minimum-necessary standard), patient identifiers in URL query
strings, and encryption explicitly disabled next to patient data.
660 → 670 patterns.
Changed
- Statistical anomaly z-scores are now computed per language group —
the eligible files sharing an extension — instead of across the whole
repository. Comment conventions differ too much between languages for
a mixed baseline to mean anything: a narrated Python file judged
against terse Rust siblings was a false outlier waiting to happen. A
group smaller than eight files supports no z-score, so files in
minority languages are not judged rather than judged against someone
else's norm; the Pareto comment-concentration detector remains
repository-total by definition. - The statistical anomaly layer is configurable:
ScanOptions::anomaly_detectorsin the core API,--no-anomaliesand
--anomaly-detectors <list>on the CLI (unknown names fail loudly
with the valid list), and ananomaly_detectorsfield in
-c/--configprofile JSON.null/unset runs all four detectors, an
empty allow-list disables the layer entirely, and a non-empty list
runs exactly the named detectors. A disabled layer also skips metric
collection during the walk.
Fixed
- Release pipeline
checksums.txtis now a usable verification file: it
lists every published archive (platform tarballs, WASM, source) in
standardsha256sum -cformat, computed from the final assembled
assets. Previously each platform job hashed its unpacked binaries, the
Windows job stripped filenames from its lines, and artifact merging
let the Windows file silently overwrite all the others — so v0.5.0
shipped four bare Windows binary hashes that matched nothing
downloadable (release assets are immutable once published, so that
file cannot be corrected in place; it is superseded from the next
release on).
v0.5.0
A statistical anomaly layer for directory scans — comment-ratio, comment-concentration, identifier-diversity, and file-size outliers reported through a new Severity::Info tier that can never fail a CI run — plus seven money-correctness rules in finance.
Changelog
Added
- Statistical anomaly layer in the engine: directory scans now collect
per-file metrics (line counts, comment share under a line-prefix
heuristic, identifier diversity) and emitSeverity::Infofindings in
the newstatistical-anomalycategory for files far outside their own
repository's baseline —comment-ratio-outlier(z > 2.5), Pareto-style
comment-concentration(one file holding ≥ 60% of repo commentary),
identifier-diversity-outlier(heavy token reuse below 0.2 diversity),
andfile-size-outlier(z > 2.5). Each detector reports only its most
extreme file; prose, dotfiles, lockfiles, and minified bundles are
excluded. Grounded in the detection-brittleness literature, the
observations are triage signals, not verdicts. Severity::Infoacross the engine: weight 0 in risk scoring,info
accepted bySeverity::parseand custom.aegis.ymlpatterns, an INFO
label in text output, SARIFnotelevel, and exclusion from the exit
code — informational findings are reported in every format but can
never fail a CI run. They also respect category, severity-threshold,
and baseline filters like every other finding.- Seven money-correctness rules in
finance, which previously only held
PII/credential detectors: money in binary floating-point fields,
toFixedcurrency rounding,Math.roundon money, exact-equality
money comparisons,parseFloatmoney parsing, unsynchronized
read-modify-write balance updates, and wall-clock settlement/expiry
timestamps. Counting-shaped identifiers (total_findings == 0) are
excluded from the equality rule. 653 → 660 patterns. - New
cryptographycategory with ten primitive-misuse rules: MD5/SHA-1
password hashing, weak HMACs, ECB mode, legacy ciphers (DES/3DES/RC4/
Blowfish), sub-15000-iteration PBKDF2, RSA without OAEP, key material
derived from non-cryptographic PRNGs (including Go:=assignments),
all-zero IVs/nonces, hard-coded salts, and timing-unsafe MAC
comparisons. 644 → 653 patterns. - Removed the byte-identical duplicate of
jwt-none-algorithmthat also
shipped assecurity-hardening-jwt-none-algorithm(same regex,
severity, and confidence in two categories); the web-security rule
remains. - Five hallucination-artifact markers in
ai-detection: retired OpenAI
/v1/enginesendpoint, doc-example placeholder credential assignments,
placeholder environment variable reads, imports of placeholder package
names, and comment-marked stub implementations — the shapes left behind
when generated code is pasted in unverified, each a silent-failure risk.
639 → 644 patterns. - Six research-grounded AI-writing markers in
ai-detection(assistant-conversation
remnants, formulaic verbs, marketing vocabulary, hedging boilerplate, academic
phrasing, emoji-led Markdown headings), informed by the detector-ablation
literature; the category page now states explicitly that these are triage
signals rather than verdicts, since formulaic human writing triggers them and
paraphrasing defeats them. 633 → 639 patterns. scripts/generate_examples.pynow emits the lint attributes on the generated
example_forlookup, so regenerating liveness examples no longer produces a
file that failsclippy -D warnings.- Hierarchical pattern catalog under
docs/patterns/: a high-level index
(scoring, scoping, severity distribution) linking one generated page per
category with every pattern's regex, metadata, and liveness-verified
example. Regenerated bycargo run -p aegis-patterns --example generate_docs; a freshness test fails CI when the pages drift. Long
credential-shaped runs in rendered examples are elided so the catalog can
live in the repository without tripping secret scanners; the exact inputs
stay compiled incrates/aegis-patterns/src/examples.rs.
Changed
- Documentation count refresh: the README category table now lists all 34
categories with per-category counts (the previous 15-row table predates
ai-detection,cryptography, and the finance expansion), and the wiki
mirror,docs/README.md,docs/PLAN.md, and the quick-start guide carry
the 660/34 totals with the current severity distribution. - Wiki and documentation audit: replaced stale references (invented install
paths, flags, config formats, release asset names) with the real CLI/MCP
surface, corrected pattern counts, and rewrote the six wiki pages to match
v0.4.0 behavior.
v0.4.0
Configuration presets on every scan invocation (-c/--config), a rule-liveness harness that proves every bundled pattern can fire, custom user patterns via .aegis.yml, and a round of correctness fixes — baseline rescans stay green, stats now agrees with findings, and the WASM scanner scans again.
Changelog
Added
-c/--configis wired on every scan invocation: a built-in preset
(production,pipeline,development,mcp-integration) or a path to a
JSON profile file supplies defaults for flags the operator did not set
(output format, categories, severity threshold); explicit flags always win.
Unknown names fail with the list of valid presets, and the built-in presets
are tested field-by-field against the shippedconfig/profiles/*.jsonso
they cannot drift.- Rule-liveness harness: 633 provably-firing example matches, one per bundled
pattern, so a pattern that cannot match anything fails CI. - Custom user patterns via
.aegis.ymlin the scan root, merged into the
registry before the walk.
Fixed
- Baseline rescans stay green:
scanno longer scans the baseline file
itself. A baseline records findings verbatim, so a rescan that included it
re-flagged every documented secret and kept the exit code red even when no
new findings existed. The baseline path is now excluded from the walk, and
the exit-code contract is verified end-to-end (0 = no new findings,
1 = new findings only). statsagrees withfindings: stdin (--stdin), env (--env), and
diff (--diff) scans folded findings into ad-hoc counters, so
--format jsoncould emitfinding_count: 0next to a non-empty
findingsarray. All scan paths now aggregate through
ScanStats::add_finding; reports and receipts agree with the finding list.- WASM scanner works:
scan_contentpreviously scanned nothing; the WASM
build now bundles the full pattern set. - Vendor-prefixed secret rules are file-active again after the noise
audit. - Noise audit round two: repaired noisy patterns and deduplicated AST
rules, cutting the project's self-scan from 941 to 817 findings and the
CI-parity self-scan (secrets, security-hardening, web-security at high+) to
0 findings. - Suppression fixtures in the MCP and daemon suites now name the rules that
actually fire and sit on the finding's own line, so inline suppression is
genuinely exercised.
Changed
- Lazy per-extension pattern compilation: patterns are grouped and compiled
once per file extension, so a TypeScript rule never runs against a Rust
file and unreachable regexes are never compiled. - Workspace-wide strict lint enforcement (
clippyall + pedantic,
rust_2018_idioms,unused_qualifications,missing_docs) with
-D warningsin CI; fail-closed scanner initialization. - Test coverage swept to 98% line coverage across the workspace, with a
coverage gate in CI. - Documentation accuracy audit: every user-facing claim re-verified against
the built binaries; public API fully documented (missing_docsenforced).
v0.3.0
What's Changed
- fix(release): single workspace version source, sync members to 0.2.7 by @aliasfoxkde in #74
- feat(cli): implement --baseline filtering of known findings by @aliasfoxkde in #75
- feat(core): suppression ranges, file-level ignores, reasons, AST coverage by @aliasfoxkde in #76
- test(mcp): give update_bundle a longer exit deadline by @aliasfoxkde in #77
- feat(cli): --staged pre-commit scan of the git index by @aliasfoxkde in #79
- feat(core): user-defined patterns via .aegis.yml by @aliasfoxkde in #78
- docs: refresh roadmap with shipped status, WCAG matrix, distribution by @aliasfoxkde in #80
- feat(quality): coverage gate, criterion bench, fuzz targets by @aliasfoxkde in #81
- chore(release): bump version to 0.3.0 by @aliasfoxkde in #82
Full Changelog: v0.2.7...v0.3.0
v0.2.7
What's Changed
- fix(release): make publication idempotent by @aliasfoxkde in #61
- docs: refresh handoff evidence boundary by @aliasfoxkde in #62
- docs: refresh merged handoff boundary by @aliasfoxkde in #63
- fix(mcp): accept documented positional scan_file params by @aliasfoxkde in #65
- fix(mcp): accept documented positional scan_dir params by @aliasfoxkde in #66
- style: format orphaned Rust sources by @aliasfoxkde in #67
- fix: keep receipt statistics aligned with findings by @aliasfoxkde in #68
- fix: fail closed on stale receipt files by @aliasfoxkde in #69
- fix(mcp): keep tracing off stdout protocol by @aliasfoxkde in #70
- Qualify Aegis as an Atheon successor by @aliasfoxkde in #64
- feat(core): implement .aegisignore with working ignore semantics by @aliasfoxkde in #71
- fix(patterns): repair noise patterns, dedupe AST rules, cut self-scan 71% by @aliasfoxkde in #72
- chore(release): bump version to 0.2.7 by @aliasfoxkde in #73
Full Changelog: v0.2.6...v0.2.7
v0.2.2
Full Changelog: v0.2.1...v0.2.2