chore(release): sync develop to main for v0.14.0 - #540
Merged
Conversation
…#526) * feat(review): defend against adversarial source-code comments (ALIBI) LLM reviewers are highly vulnerable to adversarial comments in the code under review — fabricated tool-result claims ('sanitizer passed', 'already validated') steer reviewer reasoning with >90% attack success across 125 real-world vulnerabilities (arXiv:2607.24964). Prompt-level 'ignore comments' instructions are proven ineffective against adaptive attacks. Architectural defenses (issue #524): - comment_sanitizer module: strip comments from added diff lines (opt-in, review.sanitize-comments) with quote-aware marker detection (//, leading #, --, leading ;) — line numbers preserved - Claim flagging (always on): added comments asserting verification or tool results are surfaced in review context as untrusted claims - Deterministic scanners (rules, secrets, security) always run on the unsanitized diff - SECURITY.md threat model section + configuration docs Refs #524 * fix(review): run deterministic scanners on unsanitized diff; guard decrement ops - Rules/secrets/security scanners now parse the original diff; only the LLM prompt receives the sanitized text (matches documented behavior) - '--' marker requires preceding whitespace/line-start so C/C++ decrement (i--) is not stripped as a comment - Add regression test for decrement guard Refs #524 --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
Empirical study (n=34, arXiv:2607.24601): full explanations maximize perceived trust but NOT agreement — moderate explanations achieve the highest developer agreement (89.22%). Instruct the reviewer to keep each finding at severity + short reason (1-3 sentences) + code evidence, avoiding long reasoning chains. Refs #525 Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…s) (#518) Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…tal status (#528) Running 'cora index' inside a workspace member crate resolved that crate's plain Cargo.toml as the project root, while MCP sessions resolved the workspace root — two different project rows, so index_status silently reported total_symbols: 0 despite a populated DB (#522). - resolve_project_root now prefers a Cargo.toml declaring [workspace], still honors .cora.yaml overrides first, and never climbs past a .git boundary so unrelated parent workspaces cannot hijack resolution - incremental no-op re-runs now print 'Index up to date' plus stored totals instead of a confusing 'Indexed 0 symbols from 0 files' - MCP index_status carries root-mismatch hint listing other roots with data when the resolved project has zero symbols Regression tests: workspace-root preference, .cora.yaml precedence, .git boundary stop, incremental count preservation, mismatch hint. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
… default (#529) * fix(index): resolve cross-crate method calls — cut dead-code false positives Method calls inside Rust impl blocks were never walked for call edges (only top-level free functions were), and method/qualified call targets stored the raw AST text ('self.export_full', 'std::mem::drop') which can never join against bare symbol names. Both made find_dead_code flag symbols that are called across files/crates — 557 false positives on a 5-crate workspace (#519). - impl-block function bodies now get extract_calls_from_node like free functions, recording their internal calls - new normalize_callee_name reduces targets to the final name segment, so self.x(), manager.y() and std::mem::drop() all land on x/y/drop - applies to every language routed through the shared walker Regression tests: bare-name edge extraction (AST level) and a two-file cross-crate dead-code integration mirroring the uteke case. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * feat(dead-code): skip public API surface by default (+ --include-pub) Majority of dead-code noise on library workspaces is pub API meant for external consumption — 557 findings on uteke were mostly pub fns in lib crates (#520). Missing internal callers does not make them dead. - find_dead_code skips pub (incl. pub(crate)) and export items by default, keyed off captured signatures; DeadCodeOptions.include_pub_api opts back in - new --include-pub CLI flag and include_pub_api MCP parameter - cora dead-code now resolves the project root exactly like cora index, so queries hit the same workspace project after #522 On cora-code itself: 213 findings drop to 89 with the default filter. Regression test covers pub-skip default, opt-in flag, private helper. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…#530) * feat(index): honor ignore.files — exclude matched files from indexing skip patterns only invalidated fingerprints; the walker still indexed every matching file, so dead-code and review's index scanners reported ~90 false positives per run from examples/ and extensions/ on uteke even with .cora.yaml ignore.files configured (#521). - index_project_with_id now excludes files matching skip patterns (should_skip_file glob matching) before reading them; new IndexStats.files_excluded reports the count - cora index / watch merge review's ignore.files with index.skip_files, so one ignore list governs scan, index, and dead-code alike - cora scan passes the merged list to its index-based findings stage too Config-hash invalidation already wipes prior state when the pattern list changes, so newly excluded files are purged on the next run. Regression test covers exclusion plus purge-on-new-pattern. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * chore(ci): re-trigger PR checks Signed-off-by: Anaz S. Aji <aji.anaz@gmail.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Signed-off-by: Anaz S. Aji <aji.anaz@gmail.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…#531) Review run 2 on uteke#1084 flagged a false positive: the handler validated author_type up front and set_author_type sat in a SHARED match arm fed by two producers, but build_review_prompt shipped only raw diff hunks — the LLM reconstructed branch structure from diff shape and got it wrong (#523). - new engine::enclosing module: for hunks whose add/context lines touch branching constructs, extract the enclosing function from the post-image file (brace-balance heuristic), clamped to 120 lines with head+tail windowing so shared arms stay visible without token blowup - gated injection: new files, deletions, binaries, non-branching hunks, and unreadable files are skipped - always-on prompt guardrail forbidding reachability claims unless verified against surrounding code (stage 2 of the issue proposal) - stage 3 (call-graph reachability cross-check) intentionally left out Regression tests: acceptance fixture mirrors the shared-arm case (both producers visible in injected context); negative case without branching; new-file skip; clamp bound; guardrail presence. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
…brain output (#534) Signed-off-by: Anaz S. Aji <aji.anaz@gmail.com>
…edefines the symbol (#535) Signed-off-by: Anaz S. Aji <aji.anaz@gmail.com>
…ets (#537) Reasoning models (e.g. GLM via Bifrost) can spend the entire max_tokens budget on chain-of-thought and return HTTP 200 with content: "" and finish_reason: "length". cora never read finish_reason or reasoning_content and silently fed an empty string to the JSON parser, surfacing the misleading 'EOF while parsing a value at line 1 column 0' — while the model's actual answer sat in the backend logs (cosy#63) (#536). Recovery now follows productivity over token frugality: - response parsing captures finish_reason and reasoning_content - empty content + finish_reason=length auto-retries with doubled budget (4096 -> ... -> 32768 ceiling) inside chat_completion - last resort: JSON-looking reasoning text is salvaged as the raw response; the parse layer still validates it - parse layer reports an explicit 'provider returned an EMPTY response' instead of serde EOF noise - default max_tokens raised 4096 -> 8192 for reasoning headroom Regression tests: budget escalation table, reasoning salvage (string/parts/fenced/prose), explicit empty-raw error. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
- Bump version 0.13.0 -> 0.14.0 - Promote CHANGELOG [Unreleased] to [0.14.0] (2026-08-28): empty LLM response recovery (#536), cross-crate dead-code fixes (#519), workspace root resolution (#522), ignore.files honored by index (#521), enclosing control-flow scope in review (#523), pub API skip + --include-pub (#520), relicensing to Apache-2.0 - docs: cli-reference gains dead-code --include-pub; AGENT.md test count and engine tree updated Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Sync
develop(viarelease/v0.14.0) tomainto cut the v0.14.0 release: 5 bug fixes, 3 features, license change to Apache-2.0, and the v0.14.0 version bump/CHANGELOG promotion.Highlights: empty LLM response recovery for reasoning models (#536), cross-crate method-call resolution in dead-code (#519) with public-API skip and
--include-pub(#520),ignore.fileshonored by the index (#521), workspace-root resolution + honest incremental status (#522), enclosing control-flow scope in review prompts (#523).Why
Tags must point at commits reachable from
main(enforced byrelease.ymlverify-main). Per the OSS release workflow, the develop → main sync is a PR with CI green and no admin bypass. Head branch uses therelease/prefix required by the branch-naming check.Testing
CI runs on this PR; all checks must pass before merge. Contents already validated on
develop(934 tests, fmt, clippy).