Skip to content

optimize: consolidate agent-optimization module + reversible-compression retrieve (CCR) - #204

Merged
getappz merged 15 commits into
masterfrom
flare-land
Jul 16, 2026
Merged

optimize: consolidate agent-optimization module + reversible-compression retrieve (CCR)#204
getappz merged 15 commits into
masterfrom
flare-land

Conversation

@getappz

@getappz getappz commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Consolidates the scattered agent-optimization features (caveman / ponytail / compact) into a single optimize module, and makes output-layer compression reversible via a retrieve tool (CCR pattern). Tracker items: flare #93 (parent, consolidation) and #94 (retrieve/CCR).

Decoupled from the site landing-page work (PR #203) — this branch was rebased --onto master so it carries only the consolidation commits, no site/ changes.

What's in it

Consolidation (#93)

  • src/flare/src/optimize/ (module + CLI agentflare optimize {output,code,context,…}, opt visible alias, flare hidden alias); adds mcp__flare__optimize.
  • Crates kept as brand namespace: cavemanflare-output, ponytailflare-code.
  • context layer merged from compact.rs (in-memory FTS5/BM25 transcript scorer).
  • AGENTS.md migrated to the optimize command surface (legacy flare/caveman/ponytail documented as backward-compatible aliases).

Reversible compression / retrieve (#94, CCR)

  • optimize/retrieve.rs: registers each compression's original under a short id; file-backed originals are snapshotted into an owned blob store so they survive source mutation/deletion. Atomic (temp + rename) index writes under a best-effort advisory lock; TTL + max-entry pruning that also deletes owned blobs.
  • flare-output compress() now reports original_path; the output CLI registers it and prints an expand-marker.
  • MCP optimize action=retrieve|list (list is TTL-pruned + sorted newest-first).
  • CLI agentflare optimize retrieve <id> / --list.

Verification (local)

  • cargo fmt --all --check — clean
  • cargo clippy --all-targets — clean (2 pre-existing style warnings only)
  • cargo test491 passed, 0 failed

Not included (tracked separately)

Summary by CodeRabbit

  • New Features
    • Added a unified optimize command for Flare Code minimalism, output compression, context transcript scoring, runtime/session assistance, status, and retrieval-by-id.
    • Added a reversible compression history registry for restoring originals, plus an MCP tool to list and retrieve them.
    • Improved context scoring and added persistent runtime session routing “nudges.”
  • Bug Fixes
    • Strengthened Markdown structure preservation during compression with additional validation, and improved platform session labeling.
  • Documentation
    • Updated Flare Code help/guidance cards and added changelogs/notes.
  • Deprecation / Compatibility
    • Kept legacy command aliases while shifting the primary CLI namespace and labels from Ponytail to Flare Code.

getappz added 13 commits July 16, 2026 11:11
Renamed crates: caveman->flare-output, ponytail->flare-code.
Created src/flare/ module (output/code/context/runtime layers).
New CLI: agentflare flare {output,code,context,status}.
Legacy aliases: agentflare {caveman,ponytail} kept.
Rebranded embedded .md rule files in flare-code crate.
Updated config.rs detect.rs platform.rs state.rs switcher.rs.
…module in

Consolidation module + CLI renamed flare -> optimize (flare stays the brand namespace: mcp__flare, flare-* crates). src/flare -> src/optimize, src/cli/flare.rs -> src/cli/optimize.rs, FlareArgs -> OptimizeArgs. The existing session-hygiene/routing module (src/optimize.rs) folds in as src/optimize/runtime.rs via a glob re-export, so crate::optimize::* call sites are unchanged. CLI: optimize primary; flare and opt as aliases. Brand crates and init.rs hook strings untouched.
The consolidation locked `optimize` as the module/command name (flare is the
namespace). AGENTS.md still documented `agentflare flare {output,code,context}`;
update the table + prose to `optimize` and list `agentflare flare` alongside
caveman/ponytail as a backward-compatible alias.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR consolidates output, code, context, retrieval, and runtime capabilities under agentflare optimize, renames supporting crates to flare-code and flare-output, adds CLI and MCP retrieval flows, and retains legacy command compatibility through re-exports and deprecated paths.

Changes

Optimize module consolidation

Layer / File(s) Summary
Workspace and Flare Code layer
Cargo.toml, crates/flare-code/**
The workspace adopts renamed crates, while Flare Code exposes agent detection, mode state, instructions, skills, platform formatting, and /flare-code command handling.
Flare Output compressor
crates/flare-output/**
The output crate provides compression support with prompts, LLM backends, frontmatter parsing, sensitive-path checks, structural validation, and original-path reporting.
Optimize layers and persistence
src/optimize/**
The optimize module adds code/output facades, BM25 transcript scoring, persistent retrieval entries and markers, runtime session state, routing, batching, and wake-up nudges.
CLI, hooks, and MCP integration
src/cli/*, src/mcp_*.rs, src/compact.rs
The new optimize CLI dispatches output, code, context, status, and retrieval actions; legacy paths and MCP handlers delegate to optimize APIs.
Documentation, skills, and tooling
AGENTS.md, opencode.json, crates/*/CHANGELOG.md, crates/flare-code/src/skill*.md
Documentation, changelogs, skill cards, and editor settings describe the renamed modules, commands, and optimize-layer behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Compressor
  participant Registry
  participant MCP
  CLI->>Compressor: compress input
  Compressor-->>CLI: report and original path
  CLI->>Registry: register backup and create marker
  Registry-->>CLI: retrieval id
  MCP->>Registry: retrieve id
  Registry-->>MCP: original content
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: consolidating optimization modules and adding reversible compression retrieval.
Description check ✅ Passed It explains the change, includes verification results, and gives reviewer context, though it does not follow the template headings exactly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch flare-land

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/cli/caveman.rs (1)

58-66: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Legacy caveman compress path doesn't register the CCR entry, unlike the new optimize output compress.

src/cli/optimize.rs's OutputAction::run calls record_and_marker(...) on success to register the original with the retrieve registry and print an expand marker; this duplicate success-path logic in CavemanArgs::run omits that call entirely. Content isn't lost (the backup/original still exists on disk), but users of the deprecated caveman/hidden flare alias get no short-id or hint that agentflare optimize retrieve <id> can recover it, breaking the documented recovery workflow for anyone still on the legacy entry point. Based on learnings, recovery of output-layer compressed content is expected via agentflare optimize retrieve <id>.

♻️ Proposed fix (also reduces duplication)
                 match result {
                     Ok(report) => {
                         let pct =
                             100 - (100 * report.compressed_bytes / report.original_bytes.max(1));
                         println!(
                             "{}→{}B ▼{pct}%",
                             report.original_bytes, report.compressed_bytes
                         );
+                        println!(
+                            "{}",
+                            crate::cli::optimize::record_and_marker(
+                                report.original_path.clone(),
+                                report.original_bytes as u64,
+                                report.compressed_bytes as u64,
+                                crate::optimize::retrieve::now_unix(),
+                            )
+                        );
                     }

(requires making record_and_marker in src/cli/optimize.rs at least pub(crate))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/caveman.rs` around lines 58 - 66, Update the successful compression
branch in CavemanArgs::run to invoke the existing record_and_marker helper,
matching OutputAction::run in optimize.rs. Expose record_and_marker as
pub(crate) if necessary, and pass the legacy compression result’s
original/output context so the CCR entry and expand marker are registered before
or alongside the existing summary output.

Source: Learnings

crates/flare-code/src/platform.rs (1)

68-74: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Stale assertion will fail: test still expects "PONYTAIL:FULL".

format_hook_output now emits systemMessage: "FLARE CODE:FULL" (line 39), but this test still asserts "PONYTAIL:FULL" — it will fail on the next cargo test run.

🐛 Proposed fix
-        assert_eq!(parsed["systemMessage"], "PONYTAIL:FULL");
+        assert_eq!(parsed["systemMessage"], "FLARE CODE:FULL");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-code/src/platform.rs` around lines 68 - 74, Update the expected
systemMessage assertion in codex_session_start_includes_system_message to match
the current "FLARE CODE:FULL" output produced by format_hook_output, while
preserving the existing additionalContext and hookSpecificOutput assertions.
🧹 Nitpick comments (2)
crates/flare-output/src/llm.rs (1)

29-29: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded default model may go stale.

claude-sonnet-4-5 is still a valid alias, but Anthropic ships new model generations frequently (e.g. Sonnet 4.6, Sonnet 5 already exist). Since this is only a fallback when CAVEMAN_MODEL isn't set, impact is limited, but consider documenting the override env var prominently or bumping the default periodically.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-output/src/llm.rs` at line 29, Update the fallback model
handling in the model initialization to avoid an undocumented stale hardcoded
default: prominently document the CAVEMAN_MODEL override near this
configuration, and select the currently supported default model according to the
project’s model policy. Preserve the environment-variable override behavior.
src/optimize/retrieve.rs (1)

261-278: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

retrieve() doesn't enforce TTL like active_state() does.

active_state() explicitly re-checks TTL "on read, not just at registration" (comment at line 193-195), but retrieve(id) just does a raw load_state() lookup — an id can remain retrievable past TTL_SECS until some other register()/list call happens to trigger a prune. Low impact (id holders are implicitly trusted local callers), but worth aligning for consistency with the stated TTL design intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/optimize/retrieve.rs` around lines 261 - 278, Update retrieve() to
enforce TTL on read, matching active_state() by loading the state through the
existing TTL-aware path or rechecking expiration before resolving the entry.
Ensure expired IDs are treated as unavailable while preserving current retrieval
behavior for active entries and existing error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 21-22: Update the legacy command documentation in AGENTS.md to
include the visible agentflare opt shorthand and identify agentflare flare as a
hidden legacy alias, while retaining caveman and ponytail as backward-compatible
aliases.

In `@crates/flare-code/src/skill-debt.md`:
- Line 20: Update the documented grep scan command in skill-debt.md to exclude
node_modules, .git, and build-output directories using appropriate --exclude-dir
flags, while preserving the existing flare-code pattern and recursive scan
behavior.

In `@crates/flare-code/src/skill-no-hallucination.md`:
- Around line 1-35: Complete the legacy-name migration across all embedded skill
cards: in crates/flare-code/src/skill-no-hallucination.md (lines 1-35), rename
metadata, headings, triggers, and revert text from ponytail to flare-code; apply
the same identity, comparison, trigger, invocation, and revert updates in
crates/flare-code/src/skill-playbook.md (lines 1-41) and
crates/flare-code/src/skill-review.md (lines 1-91); in
crates/flare-code/src/skill.md (lines 137-138), replace the stale Caveman
companion reference with flare-output terminology.

In `@crates/flare-code/src/skill.md`:
- Around line 29-30: Update the command reference in the skill documentation
from `/flare code` to the documented hyphenated `/flare-code` form, while
preserving the existing mode options and default behavior.

In `@crates/flare-output/src/sensitive.rs`:
- Around line 26-35: Update the sensitive-name matching logic using
SENSITIVE_NAME_TOKENS so tokens are recognized only at word boundaries rather
than through raw substring containment. Preserve matches for genuinely sensitive
names while allowing filenames such as secretary.md, tokenizer.py,
tokenomics.md, and detokenize.md to pass the compress() gate in the surrounding
sensitive-check flow.

In `@crates/flare-output/src/validate.rs`:
- Around line 17-22: Update extract_headings to remove fenced code blocks before
applying HEADING_REGEX, matching the preprocessing used by extract_inline_codes.
Preserve the existing heading capture and trimming behavior while ensuring
`#-prefixed` lines inside fenced blocks are not returned as headings.

In `@opencode.json`:
- Around line 9-10: Remove the obsolete rust-analyzer.inlayHints.enable setting
from the configuration, leaving rust-analyzer diagnostics and any per-hint-group
controls unchanged.

In `@src/cli/optimize.rs`:
- Around line 77-78: Use saturating subtraction when calculating the compression
percentage so values above 100 do not panic. Update the percentage calculation
associated with report.compressed_bytes in src/cli/optimize.rs lines 77-78 and
the corresponding calculation in src/cli/caveman.rs lines 60-61, using
100usize.saturating_sub(...) or a shared helper to keep both paths aligned.

In `@src/mcp_server.rs`:
- Around line 2195-2202: Update the "list" handler to serialize a summary
representation of each CompressionEntry rather than the full entries, excluding
the kind field and its backup_path/blob_path data. Preserve the existing state
retrieval and created_ts descending sort, and use the summary only for the final
serde_json::to_string response.
- Around line 2186-2194: Update optimize’s retrieve branch to map
RetrieveError::NotFound from retrieve::retrieve to ErrorData::invalid_params
while preserving internal_error for other failures. In the optimize list branch,
stop serializing CompressionEntry directly and construct a response
representation that omits or redacts backup_path and blob_path before returning
data over MCP.

In `@src/optimize/runtime.rs`:
- Around line 70-87: Update has_word_boundary_match to validate both sides of
each keyword match: retain the existing preceding-character check and require
the character immediately after the keyword to be non-alphabetic or the end of
text. Preserve the current scanning behavior and ensure keywords with trailing
spaces continue to work correctly.

---

Outside diff comments:
In `@crates/flare-code/src/platform.rs`:
- Around line 68-74: Update the expected systemMessage assertion in
codex_session_start_includes_system_message to match the current "FLARE
CODE:FULL" output produced by format_hook_output, while preserving the existing
additionalContext and hookSpecificOutput assertions.

In `@src/cli/caveman.rs`:
- Around line 58-66: Update the successful compression branch in
CavemanArgs::run to invoke the existing record_and_marker helper, matching
OutputAction::run in optimize.rs. Expose record_and_marker as pub(crate) if
necessary, and pass the legacy compression result’s original/output context so
the CCR entry and expand marker are registered before or alongside the existing
summary output.

---

Nitpick comments:
In `@crates/flare-output/src/llm.rs`:
- Line 29: Update the fallback model handling in the model initialization to
avoid an undocumented stale hardcoded default: prominently document the
CAVEMAN_MODEL override near this configuration, and select the currently
supported default model according to the project’s model policy. Preserve the
environment-variable override behavior.

In `@src/optimize/retrieve.rs`:
- Around line 261-278: Update retrieve() to enforce TTL on read, matching
active_state() by loading the state through the existing TTL-aware path or
rechecking expiration before resolving the entry. Ensure expired IDs are treated
as unavailable while preserving current retrieval behavior for active entries
and existing error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bc8fb9f-7792-4e68-ab93-ba48aa745eb0

📥 Commits

Reviewing files that changed from the base of the PR and between 3d93063 and bb073b7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (45)
  • AGENTS.md
  • Cargo.toml
  • crates/flare-code/CHANGELOG.md
  • crates/flare-code/Cargo.toml
  • crates/flare-code/src/config.rs
  • crates/flare-code/src/detect.rs
  • crates/flare-code/src/instructions.rs
  • crates/flare-code/src/lib.rs
  • crates/flare-code/src/platform.rs
  • crates/flare-code/src/skill-audit.md
  • crates/flare-code/src/skill-debt.md
  • crates/flare-code/src/skill-gain.md
  • crates/flare-code/src/skill-help.md
  • crates/flare-code/src/skill-no-hallucination.md
  • crates/flare-code/src/skill-playbook.md
  • crates/flare-code/src/skill-review.md
  • crates/flare-code/src/skill.md
  • crates/flare-code/src/state.rs
  • crates/flare-code/src/sub_skills.rs
  • crates/flare-code/src/switcher.rs
  • crates/flare-output/CHANGELOG.md
  • crates/flare-output/Cargo.toml
  • crates/flare-output/src/compress.rs
  • crates/flare-output/src/error.rs
  • crates/flare-output/src/frontmatter.rs
  • crates/flare-output/src/lib.rs
  • crates/flare-output/src/llm.rs
  • crates/flare-output/src/prompt.rs
  • crates/flare-output/src/sensitive.rs
  • crates/flare-output/src/validate.rs
  • crates/ponytail/src/skill-help.md
  • opencode.json
  • src/cli/caveman.rs
  • src/cli/mod.rs
  • src/cli/optimize.rs
  • src/cli/ponytail.rs
  • src/compact.rs
  • src/mcp_prompts.rs
  • src/mcp_server.rs
  • src/optimize/code.rs
  • src/optimize/context.rs
  • src/optimize/mod.rs
  • src/optimize/output.rs
  • src/optimize/retrieve.rs
  • src/optimize/runtime.rs
💤 Files with no reviewable changes (1)
  • crates/ponytail/src/skill-help.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/cli/caveman.rs (1)

58-66: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Legacy caveman compress path doesn't register the CCR entry, unlike the new optimize output compress.

src/cli/optimize.rs's OutputAction::run calls record_and_marker(...) on success to register the original with the retrieve registry and print an expand marker; this duplicate success-path logic in CavemanArgs::run omits that call entirely. Content isn't lost (the backup/original still exists on disk), but users of the deprecated caveman/hidden flare alias get no short-id or hint that agentflare optimize retrieve <id> can recover it, breaking the documented recovery workflow for anyone still on the legacy entry point. Based on learnings, recovery of output-layer compressed content is expected via agentflare optimize retrieve <id>.

♻️ Proposed fix (also reduces duplication)
                 match result {
                     Ok(report) => {
                         let pct =
                             100 - (100 * report.compressed_bytes / report.original_bytes.max(1));
                         println!(
                             "{}→{}B ▼{pct}%",
                             report.original_bytes, report.compressed_bytes
                         );
+                        println!(
+                            "{}",
+                            crate::cli::optimize::record_and_marker(
+                                report.original_path.clone(),
+                                report.original_bytes as u64,
+                                report.compressed_bytes as u64,
+                                crate::optimize::retrieve::now_unix(),
+                            )
+                        );
                     }

(requires making record_and_marker in src/cli/optimize.rs at least pub(crate))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/caveman.rs` around lines 58 - 66, Update the successful compression
branch in CavemanArgs::run to invoke the existing record_and_marker helper,
matching OutputAction::run in optimize.rs. Expose record_and_marker as
pub(crate) if necessary, and pass the legacy compression result’s
original/output context so the CCR entry and expand marker are registered before
or alongside the existing summary output.

Source: Learnings

crates/flare-code/src/platform.rs (1)

68-74: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Stale assertion will fail: test still expects "PONYTAIL:FULL".

format_hook_output now emits systemMessage: "FLARE CODE:FULL" (line 39), but this test still asserts "PONYTAIL:FULL" — it will fail on the next cargo test run.

🐛 Proposed fix
-        assert_eq!(parsed["systemMessage"], "PONYTAIL:FULL");
+        assert_eq!(parsed["systemMessage"], "FLARE CODE:FULL");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-code/src/platform.rs` around lines 68 - 74, Update the expected
systemMessage assertion in codex_session_start_includes_system_message to match
the current "FLARE CODE:FULL" output produced by format_hook_output, while
preserving the existing additionalContext and hookSpecificOutput assertions.
🧹 Nitpick comments (2)
crates/flare-output/src/llm.rs (1)

29-29: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded default model may go stale.

claude-sonnet-4-5 is still a valid alias, but Anthropic ships new model generations frequently (e.g. Sonnet 4.6, Sonnet 5 already exist). Since this is only a fallback when CAVEMAN_MODEL isn't set, impact is limited, but consider documenting the override env var prominently or bumping the default periodically.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-output/src/llm.rs` at line 29, Update the fallback model
handling in the model initialization to avoid an undocumented stale hardcoded
default: prominently document the CAVEMAN_MODEL override near this
configuration, and select the currently supported default model according to the
project’s model policy. Preserve the environment-variable override behavior.
src/optimize/retrieve.rs (1)

261-278: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

retrieve() doesn't enforce TTL like active_state() does.

active_state() explicitly re-checks TTL "on read, not just at registration" (comment at line 193-195), but retrieve(id) just does a raw load_state() lookup — an id can remain retrievable past TTL_SECS until some other register()/list call happens to trigger a prune. Low impact (id holders are implicitly trusted local callers), but worth aligning for consistency with the stated TTL design intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/optimize/retrieve.rs` around lines 261 - 278, Update retrieve() to
enforce TTL on read, matching active_state() by loading the state through the
existing TTL-aware path or rechecking expiration before resolving the entry.
Ensure expired IDs are treated as unavailable while preserving current retrieval
behavior for active entries and existing error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 21-22: Update the legacy command documentation in AGENTS.md to
include the visible agentflare opt shorthand and identify agentflare flare as a
hidden legacy alias, while retaining caveman and ponytail as backward-compatible
aliases.

In `@crates/flare-code/src/skill-debt.md`:
- Line 20: Update the documented grep scan command in skill-debt.md to exclude
node_modules, .git, and build-output directories using appropriate --exclude-dir
flags, while preserving the existing flare-code pattern and recursive scan
behavior.

In `@crates/flare-code/src/skill-no-hallucination.md`:
- Around line 1-35: Complete the legacy-name migration across all embedded skill
cards: in crates/flare-code/src/skill-no-hallucination.md (lines 1-35), rename
metadata, headings, triggers, and revert text from ponytail to flare-code; apply
the same identity, comparison, trigger, invocation, and revert updates in
crates/flare-code/src/skill-playbook.md (lines 1-41) and
crates/flare-code/src/skill-review.md (lines 1-91); in
crates/flare-code/src/skill.md (lines 137-138), replace the stale Caveman
companion reference with flare-output terminology.

In `@crates/flare-code/src/skill.md`:
- Around line 29-30: Update the command reference in the skill documentation
from `/flare code` to the documented hyphenated `/flare-code` form, while
preserving the existing mode options and default behavior.

In `@crates/flare-output/src/sensitive.rs`:
- Around line 26-35: Update the sensitive-name matching logic using
SENSITIVE_NAME_TOKENS so tokens are recognized only at word boundaries rather
than through raw substring containment. Preserve matches for genuinely sensitive
names while allowing filenames such as secretary.md, tokenizer.py,
tokenomics.md, and detokenize.md to pass the compress() gate in the surrounding
sensitive-check flow.

In `@crates/flare-output/src/validate.rs`:
- Around line 17-22: Update extract_headings to remove fenced code blocks before
applying HEADING_REGEX, matching the preprocessing used by extract_inline_codes.
Preserve the existing heading capture and trimming behavior while ensuring
`#-prefixed` lines inside fenced blocks are not returned as headings.

In `@opencode.json`:
- Around line 9-10: Remove the obsolete rust-analyzer.inlayHints.enable setting
from the configuration, leaving rust-analyzer diagnostics and any per-hint-group
controls unchanged.

In `@src/cli/optimize.rs`:
- Around line 77-78: Use saturating subtraction when calculating the compression
percentage so values above 100 do not panic. Update the percentage calculation
associated with report.compressed_bytes in src/cli/optimize.rs lines 77-78 and
the corresponding calculation in src/cli/caveman.rs lines 60-61, using
100usize.saturating_sub(...) or a shared helper to keep both paths aligned.

In `@src/mcp_server.rs`:
- Around line 2195-2202: Update the "list" handler to serialize a summary
representation of each CompressionEntry rather than the full entries, excluding
the kind field and its backup_path/blob_path data. Preserve the existing state
retrieval and created_ts descending sort, and use the summary only for the final
serde_json::to_string response.
- Around line 2186-2194: Update optimize’s retrieve branch to map
RetrieveError::NotFound from retrieve::retrieve to ErrorData::invalid_params
while preserving internal_error for other failures. In the optimize list branch,
stop serializing CompressionEntry directly and construct a response
representation that omits or redacts backup_path and blob_path before returning
data over MCP.

In `@src/optimize/runtime.rs`:
- Around line 70-87: Update has_word_boundary_match to validate both sides of
each keyword match: retain the existing preceding-character check and require
the character immediately after the keyword to be non-alphabetic or the end of
text. Preserve the current scanning behavior and ensure keywords with trailing
spaces continue to work correctly.

---

Outside diff comments:
In `@crates/flare-code/src/platform.rs`:
- Around line 68-74: Update the expected systemMessage assertion in
codex_session_start_includes_system_message to match the current "FLARE
CODE:FULL" output produced by format_hook_output, while preserving the existing
additionalContext and hookSpecificOutput assertions.

In `@src/cli/caveman.rs`:
- Around line 58-66: Update the successful compression branch in
CavemanArgs::run to invoke the existing record_and_marker helper, matching
OutputAction::run in optimize.rs. Expose record_and_marker as pub(crate) if
necessary, and pass the legacy compression result’s original/output context so
the CCR entry and expand marker are registered before or alongside the existing
summary output.

---

Nitpick comments:
In `@crates/flare-output/src/llm.rs`:
- Line 29: Update the fallback model handling in the model initialization to
avoid an undocumented stale hardcoded default: prominently document the
CAVEMAN_MODEL override near this configuration, and select the currently
supported default model according to the project’s model policy. Preserve the
environment-variable override behavior.

In `@src/optimize/retrieve.rs`:
- Around line 261-278: Update retrieve() to enforce TTL on read, matching
active_state() by loading the state through the existing TTL-aware path or
rechecking expiration before resolving the entry. Ensure expired IDs are treated
as unavailable while preserving current retrieval behavior for active entries
and existing error handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bc8fb9f-7792-4e68-ab93-ba48aa745eb0

📥 Commits

Reviewing files that changed from the base of the PR and between 3d93063 and bb073b7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (45)
  • AGENTS.md
  • Cargo.toml
  • crates/flare-code/CHANGELOG.md
  • crates/flare-code/Cargo.toml
  • crates/flare-code/src/config.rs
  • crates/flare-code/src/detect.rs
  • crates/flare-code/src/instructions.rs
  • crates/flare-code/src/lib.rs
  • crates/flare-code/src/platform.rs
  • crates/flare-code/src/skill-audit.md
  • crates/flare-code/src/skill-debt.md
  • crates/flare-code/src/skill-gain.md
  • crates/flare-code/src/skill-help.md
  • crates/flare-code/src/skill-no-hallucination.md
  • crates/flare-code/src/skill-playbook.md
  • crates/flare-code/src/skill-review.md
  • crates/flare-code/src/skill.md
  • crates/flare-code/src/state.rs
  • crates/flare-code/src/sub_skills.rs
  • crates/flare-code/src/switcher.rs
  • crates/flare-output/CHANGELOG.md
  • crates/flare-output/Cargo.toml
  • crates/flare-output/src/compress.rs
  • crates/flare-output/src/error.rs
  • crates/flare-output/src/frontmatter.rs
  • crates/flare-output/src/lib.rs
  • crates/flare-output/src/llm.rs
  • crates/flare-output/src/prompt.rs
  • crates/flare-output/src/sensitive.rs
  • crates/flare-output/src/validate.rs
  • crates/ponytail/src/skill-help.md
  • opencode.json
  • src/cli/caveman.rs
  • src/cli/mod.rs
  • src/cli/optimize.rs
  • src/cli/ponytail.rs
  • src/compact.rs
  • src/mcp_prompts.rs
  • src/mcp_server.rs
  • src/optimize/code.rs
  • src/optimize/context.rs
  • src/optimize/mod.rs
  • src/optimize/output.rs
  • src/optimize/retrieve.rs
  • src/optimize/runtime.rs
💤 Files with no reviewable changes (1)
  • crates/ponytail/src/skill-help.md
🛑 Comments failed to post (11)
AGENTS.md (1)

21-22: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document the visible opt alias.

The CLI migration retains agentflare opt as the visible shorthand, but these lines list only flare, caveman, and ponytail. Add agentflare opt, and distinguish flare as the hidden legacy alias so the documented command surface matches the PR objective.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` around lines 21 - 22, Update the legacy command documentation in
AGENTS.md to include the visible agentflare opt shorthand and identify
agentflare flare as a hidden legacy alias, while retaining caveman and ponytail
as backward-compatible aliases.
crates/flare-code/src/skill-debt.md (1)

20-20: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Make the documented scan actually skip excluded directories.

The preceding instruction promises to skip node_modules, .git, and build output, but this command has no --exclude-dir flags. It will recurse into those trees, causing noisy results and unnecessary scanning.

Proposed fix
-`grep -rnE '(#|//) ?flare-code:' .`
+`grep -rnE --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=build --exclude-dir=target '(#|//) ?flare-code:' .`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`grep -rnE --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=build --exclude-dir=target '(#|//) ?flare-code:' .`  (add other comment prefixes if your stack uses them)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-code/src/skill-debt.md` at line 20, Update the documented grep
scan command in skill-debt.md to exclude node_modules, .git, and build-output
directories using appropriate --exclude-dir flags, while preserving the existing
flare-code pattern and recursive scan behavior.
crates/flare-code/src/skill-no-hallucination.md (1)

1-35: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Complete the legacy-name migration in the embedded skill cards.

These cards still expose ponytail-* identities and triggers, while skill-help.md documents flare-code-*. Because sub_skills.rs embeds these files verbatim, users can receive stale invocation and revert instructions at runtime.

  • crates/flare-code/src/skill-no-hallucination.md#L1-L35: rename metadata, headings, triggers, and revert text to flare-code.
  • crates/flare-code/src/skill-playbook.md#L1-L41: replace ponytail identity, comparisons, triggers, and revert instructions with flare-code terminology.
  • crates/flare-code/src/skill-review.md#L1-L91: rename the review skill and all invocation/revert references consistently.
  • crates/flare-code/src/skill.md#L137-L138: replace the stale Caveman companion reference with the renamed flare-output terminology.
📍 Affects 4 files
  • crates/flare-code/src/skill-no-hallucination.md#L1-L35 (this comment)
  • crates/flare-code/src/skill-playbook.md#L1-L41
  • crates/flare-code/src/skill-review.md#L1-L91
  • crates/flare-code/src/skill.md#L137-L138
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-code/src/skill-no-hallucination.md` around lines 1 - 35,
Complete the legacy-name migration across all embedded skill cards: in
crates/flare-code/src/skill-no-hallucination.md (lines 1-35), rename metadata,
headings, triggers, and revert text from ponytail to flare-code; apply the same
identity, comparison, trigger, invocation, and revert updates in
crates/flare-code/src/skill-playbook.md (lines 1-41) and
crates/flare-code/src/skill-review.md (lines 1-91); in
crates/flare-code/src/skill.md (lines 137-138), replace the stale Caveman
companion reference with flare-output terminology.

Source: Learnings

crates/flare-code/src/skill.md (1)

29-30: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the documented hyphenated command form.

Line 30 says /flare code, while the canonical command documented in skill-help.md is /flare-code; users copying this form may fail to switch modes.

Proposed fix
- Switch: `/flare code lite|full|ultra`.
+ Switch: `/flare-code lite|full|ultra`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

unsure. Off only: "stop flare code" / "normal mode". Default: **full**.
Switch: `/flare-code lite|full|ultra`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-code/src/skill.md` around lines 29 - 30, Update the command
reference in the skill documentation from `/flare code` to the documented
hyphenated `/flare-code` form, while preserving the existing mode options and
default behavior.
crates/flare-output/src/sensitive.rs (1)

26-35: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Substring token matching causes false-positive "sensitive" blocks.

SENSITIVE_NAME_TOKENS.iter().any(|tok| normalized.contains(tok)) does raw substring containment, so common non-sensitive filenames get incorrectly refused: secretary.md (contains secret), tokenizer.py / tokenomics.md / detokenize.md (contain token). Since this directly gates compress() in crates/flare-output/src/compress.rs (line 44-46), it blocks legitimate compressions on such docs.

🛡️ Proposed fix: match tokens at word boundaries instead of raw substrings
-    let normalized: String = name
-        .to_lowercase()
-        .chars()
-        .filter(|c| !"_- .".contains(*c))
-        .collect();
-    SENSITIVE_NAME_TOKENS
-        .iter()
-        .any(|tok| normalized.contains(tok))
+    // Split on separators instead of stripping them, so tokens must match a
+    // whole "word" in the name rather than an arbitrary substring (avoids
+    // "secretary" matching "secret", "tokenizer" matching "token", etc.).
+    let lower = name.to_lowercase();
+    lower
+        .split(|c: char| "_- .".contains(c))
+        .any(|word| SENSITIVE_NAME_TOKENS.contains(&word))

Also applies to: 52-60

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-output/src/sensitive.rs` around lines 26 - 35, Update the
sensitive-name matching logic using SENSITIVE_NAME_TOKENS so tokens are
recognized only at word boundaries rather than through raw substring
containment. Preserve matches for genuinely sensitive names while allowing
filenames such as secretary.md, tokenizer.py, tokenomics.md, and detokenize.md
to pass the compress() gate in the surrounding sensitive-check flow.
crates/flare-output/src/validate.rs (1)

17-22: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

extract_headings doesn't exclude fenced code blocks, unlike extract_inline_codes.

A #-prefixed line inside a fenced code block (a shell/Python/YAML comment) is picked up by HEADING_REGEX as a markdown heading, since extract_headings runs on the raw text. extract_inline_codes (lines 72-83) already strips fenced blocks first for exactly this reason — headings should do the same for consistency and to avoid confusing "Headings not preserved" error text when code containing # comments is involved.

♻️ Proposed fix: strip fenced blocks before extracting headings
 fn extract_headings(text: &str) -> Vec<(String, String)> {
-    HEADING_REGEX
-        .captures_iter(text)
+    let mut without_fences = text.to_string();
+    for block in extract_code_blocks(text) {
+        without_fences = without_fences.replacen(&block, "", 1);
+    }
+    HEADING_REGEX
+        .captures_iter(&without_fences)
         .map(|c| (c[1].to_string(), c[2].trim().to_string()))
         .collect()
 }

Also applies to: 72-83

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/flare-output/src/validate.rs` around lines 17 - 22, Update
extract_headings to remove fenced code blocks before applying HEADING_REGEX,
matching the preprocessing used by extract_inline_codes. Preserve the existing
heading capture and trimming behavior while ensuring `#-prefixed` lines inside
fenced blocks are not returned as headings.
opencode.json (1)

9-10: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
python -m json.tool opencode.json >/dev/null
if rg -n '"rust-analyzer\.inlayHints\.enable"' opencode.json; then
  echo "obsolete rust-analyzer setting remains" >&2
  exit 1
fi

Repository: getappz/agentflare

Length of output: 246


Remove the obsolete rust-analyzer.inlayHints.enable setting. rust-analyzer now uses per-hint-group controls, so this key is ignored and the intended inlay-hints policy won't apply.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@opencode.json` around lines 9 - 10, Remove the obsolete
rust-analyzer.inlayHints.enable setting from the configuration, leaving
rust-analyzer diagnostics and any per-hint-group controls unchanged.
src/cli/optimize.rs (1)

77-78: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== target lines ==\n'
sed -n '1,140p' src/cli/optimize.rs
printf '\n== caveman ==\n'
sed -n '1,140p' src/cli/caveman.rs

printf '\n== find compress impl and report struct ==\n'
rg -n "struct Report|fn compress|compressed_bytes|original_bytes|saturating_sub|100 - \(100 \* report\.compressed_bytes" -S .

Repository: getappz/agentflare

Length of output: 9893


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,260p' crates/flare-output/src/compress.rs
printf '\n== tests around report bytes ==\n'
sed -n '260,360p' crates/flare-output/src/compress.rs

Repository: getappz/agentflare

Length of output: 13185


🏁 Script executed:

python3 - <<'PY'
def pct(o, c):
    return 100 - (100 * c // max(o, 1))

cases = [
    (100, 100),
    (100, 101),
    (1000, 1000),
    (1000, 1001),
    (1000, 1010),
    (99, 100),
    (10, 11),
]
for o, c in cases:
    q = 100 * c // max(o, 1)
    print(f"original={o:4} compressed={c:4} term={q:3} pct={pct(o,c)}")
PY

Repository: getappz/agentflare

Length of output: 476


Use saturating subtraction for the compression percentage src/cli/optimize.rs:77 and src/cli/caveman.rs:60 can panic when the final file size pushes the integer percentage above 100; switch to 100usize.saturating_sub(...) or a shared helper so both paths stay aligned.

📍 Affects 2 files
  • src/cli/optimize.rs#L77-L78 (this comment)
  • src/cli/caveman.rs#L60-L61
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/optimize.rs` around lines 77 - 78, Use saturating subtraction when
calculating the compression percentage so values above 100 do not panic. Update
the percentage calculation associated with report.compressed_bytes in
src/cli/optimize.rs lines 77-78 and the corresponding calculation in
src/cli/caveman.rs lines 60-61, using 100usize.saturating_sub(...) or a shared
helper to keep both paths aligned.
src/mcp_server.rs (2)

2186-2194: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
ast-grep run --pattern 'enum RetrieveError { $$$ }' --lang rust src/optimize/retrieve.rs
rg -n "enum RetrieveError" -A 8 src/optimize/retrieve.rs

Repository: getappz/agentflare

Length of output: 409


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the optimize handler and surrounding code in src/mcp_server.rs
nl -ba src/mcp_server.rs | sed -n '2160,2235p'

printf '\n--- CompressionEntry / EntryKind definitions ---\n'
rg -n "struct CompressionEntry|enum EntryKind|backup_path|blob_path" -A 8 -B 4 src/mcp_server.rs src/optimize -g '*.rs'

Repository: getappz/agentflare

Length of output: 196


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba src/mcp_server.rs | sed -n '2178,2225p'

printf '\n--- nearby optimize-related type definitions ---\n'
rg -n "struct CompressionEntry|enum EntryKind|backup_path|blob_path|Serialize" -A 10 -B 4 src/mcp_server.rs src -g '*.rs'

Repository: getappz/agentflare

Length of output: 196


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- retrieve implementation ---'
rg -n "pub fn retrieve|fn retrieve" -A 40 -B 6 src/optimize/retrieve.rs

printf '\n%s\n' '--- CompressionEntry / EntryKind definitions and serialization derives ---'
rg -n "struct CompressionEntry|enum EntryKind|derive\\(" -A 12 -B 4 src/mcp_server.rs src/optimize -g '*.rs'

Repository: getappz/agentflare

Length of output: 27994


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- optimize() handler in src/mcp_server.rs ---'
sed -n '2180,2215p' src/mcp_server.rs

printf '\n%s\n' '--- optimize-related response types / serde derives ---'
rg -n "CompressionEntry|EntryKind|retrieve::retrieve|to_string_pretty|serde_json::to_value|list" -A 8 -B 4 src/mcp_server.rs src/optimize -g '*.rs'

Repository: getappz/agentflare

Length of output: 50375


Map missing compression ids to invalid_params, and redact paths from optimize(list)

  • retrieve already returns RetrieveError::NotFound(_) for unknown ids, so surface that as invalid_params instead of internal_error.
  • list serializes CompressionEntry directly, which includes EntryKind::FileBackup { backup_path } and EntryKind::Inline { blob_path }; that leaks local paths over the MCP boundary.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp_server.rs` around lines 2186 - 2194, Update optimize’s retrieve
branch to map RetrieveError::NotFound from retrieve::retrieve to
ErrorData::invalid_params while preserving internal_error for other failures. In
the optimize list branch, stop serializing CompressionEntry directly and
construct a response representation that omits or redacts backup_path and
blob_path before returning data over MCP.

2195-2202: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n "struct CompressionEntry" -A 12 src/optimize/retrieve.rs
rg -n "enum EntryKind" -A 8 src/optimize/retrieve.rs

Repository: getappz/agentflare

Length of output: 756


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant types and their constructors/usages.
ast-grep outline src/optimize/retrieve.rs --view expanded

echo '--- usages of EntryKind variants ---'
rg -n "EntryKind::(FileBackup|Inline|LeanCtxRead)|backup_path|blob_path|CompressionEntry \{" src/optimize -A 3 -B 3

echo '--- check serialization derive on the types ---'
sed -n '1,80p' src/optimize/retrieve.rs

Repository: getappz/agentflare

Length of output: 17091


Redact kind from list output CompressionEntry serializes EntryKind::{FileBackup, Inline} verbatim, so this endpoint leaks backup_path / blob_path to MCP clients. Return a summary here instead of the full entry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp_server.rs` around lines 2195 - 2202, Update the "list" handler to
serialize a summary representation of each CompressionEntry rather than the full
entries, excluding the kind field and its backup_path/blob_path data. Preserve
the existing state retrieval and created_ts descending sort, and use the summary
only for the final serde_json::to_string response.
src/optimize/runtime.rs (1)

70-87: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Word-boundary check is one-sided — only the preceding character is checked, not the following one.

Keywords without a built-in trailing separator ("where is", "where's", "search for") can false-positive when immediately followed by more letters, e.g. "search formation" contains the literal substring "search for" preceded by a space, so this currently reports a match even though the real word is "formation". "find "/"locate " are accidentally safe only because they embed a trailing space.

🐛 Proposed fix: add a symmetric trailing-boundary check
 fn has_word_boundary_match(text: &str, keyword: &str) -> bool {
     let bytes = text.as_bytes();
     let mut start = 0;
     while let Some(pos) = text[start..].find(keyword) {
         let abs_pos = start + pos;
+        let end_pos = abs_pos + keyword.len();
         let preceded_ok = abs_pos == 0 || !bytes[abs_pos - 1].is_ascii_alphabetic();
-        if preceded_ok {
+        let followed_ok = end_pos >= bytes.len() || !bytes[end_pos].is_ascii_alphabetic();
+        if preceded_ok && followed_ok {
             return true;
         }
         start = abs_pos + keyword.len().max(1);
         if start > text.len() {
             break;
         }
     }
     false
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

const LOCATE_KEYWORDS: &[&str] = &["find ", "where is", "where's", "search for", "locate "];

fn has_word_boundary_match(text: &str, keyword: &str) -> bool {
    let bytes = text.as_bytes();
    let mut start = 0;
    while let Some(pos) = text[start..].find(keyword) {
        let abs_pos = start + pos;
        let end_pos = abs_pos + keyword.len();
        let preceded_ok = abs_pos == 0 || !bytes[abs_pos - 1].is_ascii_alphabetic();
        let followed_ok = end_pos >= bytes.len() || !bytes[end_pos].is_ascii_alphabetic();
        if preceded_ok && followed_ok {
            return true;
        }
        start = abs_pos + keyword.len().max(1);
        if start > text.len() {
            break;
        }
    }
    false
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/optimize/runtime.rs` around lines 70 - 87, Update has_word_boundary_match
to validate both sides of each keyword match: retain the existing
preceding-character check and require the character immediately after the
keyword to be non-alphabetic or the end of text. Preserve the current scanning
behavior and ensure keywords with trailing spaces continue to work correctly.

getappz added 2 commits July 16, 2026 11:33
…test

CI runs clippy -D warnings and cargo test --workspace, which the consolidation tripped:
- cli/optimize.rs: drop needless &transcript borrow (needless_borrows_for_generic_args)
- cli/optimize.rs: sessions.values() instead of iter().map(|(_, r)|) (iter_kv_map)
- flare-code/platform.rs: test still expected the pre-rebrand PONYTAIL:FULL codex
  system message; production now emits FLARE CODE:FULL
…legacy CCR)

- cli: use 100usize.saturating_sub for compression %, avoiding an unsigned
  underflow panic when the compressed file ends up larger than the original
  (optimize output + legacy caveman paths)
- mcp optimize list: return a summary (id/kind-label/sizes/ts) instead of the
  full CompressionEntry, so backup_path/blob_path are no longer leaked to clients
  (new retrieve::kind_label helper)
- legacy caveman compress: register the CCR original + print the expand marker,
  matching optimize output compress (record_and_marker made pub(crate))

Rebrand of embedded skill cards + CAVEMAN_MODEL env var deferred to a follow-up
(live invocation-name compat) — tracked separately.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/mcp_server.rs (2)

2188-2193: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return invalid parameters for unknown or blank retrieval IDs.

Line 2189 only checks presence, and Line 2192 maps RetrieveError::NotFound to internal_error. A stale, empty, or mistyped ID is caller input and should not be reported as a server failure.

Proposed fix
-                let id = req.id.ok_or_else(|| {
-                    ErrorData::invalid_params("id is required for retrieve", None)
-                })?;
-                crate::optimize::retrieve::retrieve(&id)
-                    .map_err(|e| ErrorData::internal_error(e.to_string(), None))
+                let id = req
+                    .id
+                    .filter(|id| !id.trim().is_empty())
+                    .ok_or_else(|| {
+                        ErrorData::invalid_params("id is required for retrieve", None)
+                    })?;
+                match crate::optimize::retrieve::retrieve(&id) {
+                    Ok(content) => Ok(content),
+                    Err(crate::optimize::retrieve::RetrieveError::NotFound(_)) => {
+                        Err(ErrorData::invalid_params("unknown retrieve id", None))
+                    }
+                    Err(e) => Err(ErrorData::internal_error(e.to_string(), None)),
+                }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp_server.rs` around lines 2188 - 2193, Update the "retrieve" request
handling to reject blank or unknown IDs as invalid parameters: validate the
supplied id after the existing presence check, and map retrieve failures
indicating a missing record to ErrorData::invalid_params instead of
internal_error. Preserve internal_error mapping for genuine server-side
retrieval failures.

2192-2193: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Apply the TTL check to retrieval too. retrieve() reads the raw registry, so an expired CCR entry can still be fetched by ID after it disappears from list. Route retrieval through the pruned active state or reject expired entries before loading the content.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp_server.rs` around lines 2192 - 2193, Update the retrieval handler
around crate::optimize::retrieve::retrieve to enforce CCR TTL expiration before
loading content. Route the lookup through the same pruned active registry state
used by listing, or validate the entry’s expiration and reject it when expired,
while preserving the existing internal-error mapping for valid retrieval
failures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/mcp_server.rs`:
- Around line 2188-2193: Update the "retrieve" request handling to reject blank
or unknown IDs as invalid parameters: validate the supplied id after the
existing presence check, and map retrieve failures indicating a missing record
to ErrorData::invalid_params instead of internal_error. Preserve internal_error
mapping for genuine server-side retrieval failures.
- Around line 2192-2193: Update the retrieval handler around
crate::optimize::retrieve::retrieve to enforce CCR TTL expiration before loading
content. Route the lookup through the same pruned active registry state used by
listing, or validate the entry’s expiration and reject it when expired, while
preserving the existing internal-error mapping for valid retrieval failures.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4521df86-6264-4fd3-b85c-fb85f7373069

📥 Commits

Reviewing files that changed from the base of the PR and between 9201fbf and 8a2a6de.

📒 Files selected for processing (4)
  • src/cli/caveman.rs
  • src/cli/optimize.rs
  • src/mcp_server.rs
  • src/optimize/retrieve.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/cli/caveman.rs
  • src/optimize/retrieve.rs
  • src/cli/optimize.rs

@getappz
getappz merged commit 97fbe2e into master Jul 16, 2026
15 checks passed
@getappz
getappz deleted the flare-land branch July 16, 2026 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant