Repository navigation
Conversation
… an ancestor A workspace member whose manifest_dir contains other members underneath it (e.g. the root agentflare binary crate, whose manifest_dir is the repo root) was reporting those members' own files twice: once correctly attributed, once again mislabeled as a direct reference from the ancestor crate. Filter every cross-crate hit through resolve_owner_crate so it only counts toward the crate that actually owns the file.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds workspace impact analysis for Rust files. The change builds a workspace dependency graph, confirms cross-crate references, exposes shared analysis logic, and adds the ChangesCode impact analysis
Git workflow integration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant impact_for_path
participant WorkspaceGraph
participant search_crate_dir
CLI->>impact_for_path: analyze target path
impact_for_path->>WorkspaceGraph: resolve owner and reverse dependents
WorkspaceGraph-->>impact_for_path: workspace dependency data
impact_for_path->>search_crate_dir: confirm crate references
search_crate_dir-->>impact_for_path: matching impact hits
impact_for_path-->>CLI: ImpactReport
CLI-->>CLI: render text or JSON
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@src/cli/code.rs`:
- Around line 21-30: Update the ImpactArgs argument definitions and validation
so --stdin cannot be combined with a positional target. Use the clap conflict
configuration or return a usage error before the opts.stdin processing branch,
while preserving standalone --stdin and target behavior.
In `@src/code/confirm.rs`:
- Around line 19-31: Update try_lean_ctx_grep so fallback_scan is triggered only
when spawning lean-ctx fails, while a successfully launched command with a
non-zero exit status is surfaced as a search failure. Preserve the existing
successful-output parsing through parse_lean_ctx_grep_output.
In `@src/code/mod.rs`:
- Around line 47-54: Normalize the path assigned to absolute_target before
passing it to graph.resolve_owner_crate, using lexical normalization rather than
canonicalize so nonexistent targets remain supported. Ensure traversal segments
such as “..” cannot falsely remain under the workspace prefix, and add a
regression test covering a target that escapes its apparent crate directory.
In `@src/code/workspace_graph.rs`:
- Around line 68-70: Preserve Cargo dependency aliases throughout reference
analysis: in src/code/workspace_graph.rs lines 68-70, extend MetaDep and graph
construction to retain each dependency name alongside its package ID and
dependent crate; in src/code/mod.rs lines 86-95, search using each dependent’s
normalized Rust import name rather than only owner.name; in
tests/code_impact_test.rs lines 65-91, add a renamed-dependency fixture and
assert the aliased import reference is reported.
🪄 Autofix
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
Run ID: 5f16c74a-88b0-4e6c-bf35-352b02abada4
📒 Files selected for processing (9)
Cargo.tomlsrc/cli/code.rssrc/cli/mod.rssrc/code/confirm.rssrc/code/mod.rssrc/code/workspace_graph.rssrc/lib.rssrc/main.rstests/code_impact_test.rs
| pub struct ImpactArgs { | ||
| /// File path. Omit when using --stdin. | ||
| pub target: Option<PathBuf>, | ||
| /// Read a newline-separated file list from stdin (e.g. pipe | ||
| /// `git diff --name-only`) and report the union of their impact. | ||
| #[arg(long)] | ||
| pub stdin: bool, | ||
| /// Emit JSON instead of text. | ||
| #[arg(long)] | ||
| pub json: bool, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/sh
set -eu
printf '%s\n' '== available code-intelligence commands =='
command -v lean-ctx || true
command -v ctx_search || true
command -v ctx_read || true
command -v agentflare || true
printf '%s\n' '== relevant repository files =='
git ls-files | rg '(^|/)src/cli/code\.rs$|(^|/)Cargo\.toml$|(^|/)Cargo\.lock$' || true
printf '%s\n' '== src/cli/code.rs context =='
sed -n '1,120p' src/cli/code.rs
printf '%s\n' '== ImpactArgs and call sites =='
rg -n -C 4 'ImpactArgs|impact|\.stdin|target' src Cargo.toml 2>/dev/null || trueRepository: getappz/agentflare
Length of output: 50375
🏁 Script executed:
#!/bin/sh
set -eu
printf '%s\n' '== relevant CLI definitions =='
rg -n -C 8 'CodeArgs|CodeCommand|ImpactArgs|Impact\(' src/cli src/main.rs src 2>/dev/null \
| head -n 240
printf '%s\n' '== clap dependency =='
rg -n -C 2 '^clap\s*=|clap::' Cargo.toml Cargo.lock | head -n 120
printf '%s\n' '== exact impact implementation =='
nl -ba src/cli/code.rs | sed -n '15,75p'
printf '%s\n' '== focused static behavior verifier =='
python3 - <<'PY'
from pathlib import Path
p = Path("src/cli/code.rs")
text = p.read_text()
assert "pub target: Option<PathBuf>" in text
assert "#[arg(long)]\n pub stdin: bool" in text
assert "let targets: Vec<PathBuf> = if opts.stdin {" in text
assert "match opts.target {" in text
stdin_branch = text.split("let targets: Vec<PathBuf> = if opts.stdin {", 1)[1].split(
" } else {", 1
)[0]
assert "opts.target" not in stdin_branch
print("Both fields are independently accepted by the declarations.")
print("When opts.stdin is true, the implementation enters the stdin branch.")
print("The stdin branch does not read opts.target; a supplied positional target is ignored.")
PYRepository: getappz/agentflare
Length of output: 6606
🏁 Script executed:
#!/bin/sh
set -eu
printf '%s\n' '== relevant CLI definitions =='
rg -n -C 8 'CodeArgs|CodeCommand|ImpactArgs|Impact\(' src/cli src/main.rs src 2>/dev/null \
| head -n 240
printf '%s\n' '== clap dependency =='
rg -n -C 2 '^clap\s*=|clap::' Cargo.toml Cargo.lock | head -n 120
printf '%s\n' '== exact impact implementation =='
nl -ba src/cli/code.rs | sed -n '15,75p'
printf '%s\n' '== focused static behavior verifier =='
python3 - <<'PY'
from pathlib import Path
text = Path("src/cli/code.rs").read_text()
assert "pub target: Option<PathBuf>" in text
assert "#[arg(long)]\n pub stdin: bool" in text
assert "let targets: Vec<PathBuf> = if opts.stdin {" in text
assert "match opts.target {" in text
stdin_branch = text.split(
"let targets: Vec<PathBuf> = if opts.stdin {", 1
)[1].split(" } else {", 1)[0]
assert "opts.target" not in stdin_branch
print("Both fields are independently accepted by the declarations.")
print("When opts.stdin is true, the implementation enters the stdin branch.")
print("The stdin branch does not read opts.target; a supplied positional target is ignored.")
PYRepository: getappz/agentflare
Length of output: 6606
Reject a positional target with --stdin.
When both inputs are present, the opts.stdin branch reads stdin and ignores target. Add conflicting arguments or return a usage error.
🤖 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/code.rs` around lines 21 - 30, Update the ImpactArgs argument
definitions and validation so --stdin cannot be combined with a positional
target. Use the clap conflict configuration or return a usage error before the
opts.stdin processing branch, while preserving standalone --stdin and target
behavior.
| fn try_lean_ctx_grep(dir: &Path, pattern: &str) -> Option<Vec<ConfirmHit>> { | ||
| let output = Command::new("lean-ctx") | ||
| .arg("grep") | ||
| .arg(pattern) | ||
| .arg(dir) | ||
| .output() | ||
| .ok()?; | ||
| if !output.status.success() { | ||
| return None; | ||
| } | ||
| let text = String::from_utf8_lossy(&output.stdout); | ||
| Some(parse_lean_ctx_grep_output(&text, dir)) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -u
printf '%s\n' '--- intelligence tool availability ---'
command -v ctx_search || true
command -v ctx_callgraph || true
command -v ctx_compose || true
command -v ctx_read || true
command -v ctx_shell || true
printf '%s\n' '--- memory context ---'
if command -v agentflare >/dev/null 2>&1; then
agentflare memory context || true
else
printf '%s\n' 'agentflare unavailable'
fi
printf '%s\n' '--- candidate files ---'
git ls-files | grep -E '(^|/)confirm\.rs$|(^|/)Cargo\.toml$|(^|/)README' || true
printf '%s\n' '--- relevant symbols and commands ---'
rg -n --glob '*.rs' --glob '*.toml' --glob '*.md' \
'try_lean_ctx_grep|parse_lean_ctx_grep_output|lean-ctx|ctx_search|agentflare optimize|agentflare grep|regex scanner' . || true
printf '%s\n' '--- source outline ---'
if command -v ast-grep >/dev/null 2>&1 && [ -f src/code/confirm.rs ]; then
ast-grep outline src/code/confirm.rs || true
fi
printf '%s\n' '--- source section ---'
if [ -f src/code/confirm.rs ]; then
sed -n '1,180p' src/code/confirm.rs
fiRepository: getappz/agentflare
Length of output: 28811
🏁 Script executed:
#!/bin/bash
set -u
printf '%s\n' '--- intelligence tool availability ---'
command -v ctx_search || true
command -v ctx_callgraph || true
command -v ctx_compose || true
command -v ctx_read || true
command -v ctx_shell || true
printf '%s\n' '--- memory context ---'
if command -v agentflare >/dev/null 2>&1; then
agentflare memory context || true
else
printf '%s\n' 'agentflare unavailable'
fi
printf '%s\n' '--- relevant files and symbols ---'
git ls-files | grep -E '(^|/)confirm\.rs$|(^|/)Cargo\.toml$|(^|/)README' || true
rg -n --glob '*.rs' --glob '*.toml' --glob '*.md' \
'try_lean_ctx_grep|parse_lean_ctx_grep_output|lean-ctx|ctx_search|agentflare optimize|regex scanner' . || true
printf '%s\n' '--- source ---'
if [ -f src/code/confirm.rs ]; then
sed -n '1,180p' src/code/confirm.rs
fiRepository: getappz/agentflare
Length of output: 28186
🏁 Script executed:
#!/bin/bash
set -u
printf '%s\n' '--- repository guidance ---'
sed -n '31,58p' AGENTS.md
printf '%s\n' '--- code search integration ---'
sed -n '170,230p' src/mcp_server/search.rs
printf '%s\n' '--- search command declarations ---'
rg -n -C 5 'ctx_search|gateway_execute|Command::new\("lean-ctx"\)|\.arg\("grep"\)' \
src crates AGENTS.md README.md
printf '%s\n' '--- package and history metadata ---'
sed -n '1,120p' Cargo.toml
git status --short
git log --oneline -8 -- src/code/confirm.rsRepository: getappz/agentflare
Length of output: 19347
🌐 Web query:
yvgude lean-ctx ctx_search CLI grep command documentation
💡 Result:
The command you are asking about is part of LeanCTX (Lean Context), a context engineering layer for AI coding agents [1][2]. In the LeanCTX ecosystem, the CLI command and the corresponding MCP (Model Context Protocol) tool serve different purposes regarding searching your codebase [3][4][5]. CLI Command: lean-ctx grep The CLI command for text-based searching is lean-ctx grep [path] [6][7]. It is designed to perform regex-based searches across your codebase and returns compressed, grouped output [6][3]. It uses the ripgrep utility internally to ensure speed and efficiency [6]. MCP Tool: ctx_search The ctx_search tool is an MCP tool used by AI agents to perform semantic or indexed searches [3][8][4]. Unlike grep, which searches raw files, ctx_search queries an indexed knowledge base using a multi-strategy ranking pipeline (often including Porter stemming, trigram substring matching, and fuzzy correction) [3][9][10]. Key Differences and Usage 1. lean-ctx grep: Use this when you know the exact string, regex, or pattern you are looking for in the files [3]. 2. ctx_search: Use this when you are searching for concepts, or when your AI agent needs to retrieve relevant context from indexed project knowledge without reading raw files into the conversation context [3][9][11]. Note: You may encounter search results referring to a mksglu/context-mode project [9][12]. This is a separate project that also uses tools named ctx_search and ctx_index, but it is distinct from the yvgude/lean-ctx project [1][12]. Always ensure you are consulting the documentation for the specific integration you have installed [5][11].
Citations:
- 1: https://github.com/yvgude/lean-ctx
- 2: https://github.com/yvgude/lean-ctx/tree/refs/heads/main
- 3: https://github.com/yvgude/lean-ctx/blob/HEAD/docs/reference/02-daily-use.md
- 4: https://github.com/yvgude/lean-ctx/blob/main/LEAN-CTX.md
- 5: https://github.com/yvgude/lean-ctx/tree/main/docs/reference
- 6: https://leanctx.com/docs/cli-reference/
- 7: https://github.com/yvgude/lean-ctx/blob/main/docs/reference/appendix-cli-map.md
- 8: https://github.com/yvgude/lean-ctx/blob/main/docs/reference/appendix-mcp-tools.md
- 9: https://glama.ai/mcp/servers/mksglu/context-mode/tools/ctx_search
- 10: https://deepwiki.com/mksglu/context-mode/4.5-content-search-(ctx_search)
- 11: https://claudeskills.info/skills/mksglu/context-mode/ctx-search/
- 12: https://github.com/mksglu/context-mode/tree/b14d547933aed611772408cf22018d45eb7fda31
🏁 Script executed:
#!/bin/bash
set -u
printf '%s\n' '--- confirm call sites and module context ---'
rg -n -C 8 'search_crate_dir|mod confirm|pub mod code|code::' src crates
printf '%s\n' '--- gateway implementation and call sites ---'
sed -n '1,90p' src/mcp_server/search.rs
rg -n -C 6 'gateway_execute|Gateway|gateway' src/mcp_server src/code src/cli src/main.rs src/lib.rs
printf '%s\n' '--- code command surface ---'
if [ -f src/code/mod.rs ]; then
sed -n '1,130p' src/code/mod.rs
fi
printf '%s\n' '--- commit summary ---'
git show --stat --oneline 44f6c81
git show --format= --no-ext-diff 44f6c81 -- src/code/confirm.rs src/code/mod.rs | sed -n '1,240p'Repository: getappz/agentflare
Length of output: 50374
🏁 Script executed:
#!/bin/bash
set -u
python3 - <<'PY'
from pathlib import Path
import subprocess
confirm = Path("src/code/confirm.rs").read_text()
mcp_search = Path("src/mcp_server/search.rs").read_text()
fn = confirm.split("fn try_lean_ctx_grep", 1)[1].split("///", 1)[0]
assert 'Command::new("lean-ctx")' in fn
assert '.arg("grep")' in fn
assert 'ctx_search' not in fn
assert 'gateway_execute("leanctx", "ctx_search"' in mcp_search
# Model the two subprocess outcomes used by the Rust branch:
# spawn failure => output().ok()? returns None; nonzero status => explicit None.
try:
subprocess.run(
["definitely-missing-lean-ctx-for-check"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
except FileNotFoundError:
spawn_failure_falls_back = True
else:
spawn_failure_falls_back = False
nonzero = subprocess.run(
["sh", "-c", "exit 7"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
nonzero_status_falls_back = nonzero.returncode != 0
print({
"uses_documented_cli": 'Command::new("lean-ctx")' in fn and '.arg("grep")' in fn,
"ctx_search_is_mcp_gateway_only_in_repository": (
'ctx_search' not in fn and
'gateway_execute("leanctx", "ctx_search"' in mcp_search
),
"spawn_failure_falls_back": spawn_failure_falls_back,
"nonzero_status_falls_back": nonzero_status_falls_back,
})
PYRepository: getappz/agentflare
Length of output: 309
Handle non-zero lean-ctx grep exits separately. lean-ctx grep is the documented CLI for this synchronous path. The current code also falls back after any non-zero exit, not only when lean-ctx is unavailable. Surface search failures or restrict fallback_scan to spawn failures.
🤖 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/code/confirm.rs` around lines 19 - 31, Update try_lean_ctx_grep so
fallback_scan is triggered only when spawning lean-ctx fails, while a
successfully launched command with a non-zero exit status is surfaced as a
search failure. Preserve the existing successful-output parsing through
parse_lean_ctx_grep_output.
Source: Coding guidelines
| let absolute_target = if target.is_absolute() { | ||
| target.to_path_buf() | ||
| } else { | ||
| repo_root.join(target) | ||
| }; | ||
| let owner = graph | ||
| .resolve_owner_crate(&absolute_target) | ||
| .ok_or_else(|| ImpactError::NotInWorkspace(absolute_target.clone()))?; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- lean-ctx availability ---'
command -v ctx_search || true
command -v ctx_callgraph || true
command -v ctx_compose || true
command -v ctx_read || true
command -v ctx_shell || true
printf '%s\n' '--- candidate files ---'
git ls-files | rg '(^|/)(mod\.rs|Cargo\.toml)$|test' | head -200
printf '%s\n' '--- relevant symbols and path checks ---'
rg -n -C 5 'resolve_owner_crate|NotInWorkspace|absolute_target|starts_with|canonicalize|normalize' src tests 2>/dev/null | head -300Repository: getappz/agentflare
Length of output: 20878
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- src/code/mod.rs outline and implementation ---'
ast-grep outline src/code/mod.rs 2>/dev/null || true
sed -n '1,180p' src/code/mod.rs
printf '%s\n' '--- owner-resolution definitions and callers ---'
rg -n -C 12 'resolve_owner_crate|struct .*Graph|impl .*Graph|manifest_dir|owner_crate' src tests crates 2>/dev/null | head -500
printf '%s\n' '--- impact tests ---'
sed -n '1,260p' tests/code_impact_test.rsRepository: getappz/agentflare
Length of output: 36700
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- path construction and impact callers ---'
rg -n -C 10 'impact_for_path\(|PathBuf|canonicalize\(|normalize|code impact' src tests | head -500
printf '%s\n' '--- path semantics probe ---'
python3 - <<'PY'
from pathlib import PurePath
root = PurePath('/workspace')
raw = root / 'crates/jobs/../../outside.rs'
owner = root / 'crates/jobs'
manifest_other = root / 'crates/top'
def lexical_components(path):
return path.parts
print('raw:', raw)
print('raw components:', lexical_components(raw))
print('raw starts_with jobs:', lexical_components(raw)[:len(owner.parts)] == owner.parts)
print('raw starts_with top:', lexical_components(raw)[:len(manifest_other.parts)] == manifest_other.parts)
parts = []
for part in raw.parts:
if part == '..':
if parts and parts[-1] != '/':
parts.pop()
elif part != '.':
parts.append(part)
normalized = PurePath(*parts)
print('normalized:', normalized)
print('normalized starts_with jobs:', lexical_components(normalized)[:len(owner.parts)] == owner.parts)
print('normalized starts_with top:', lexical_components(normalized)[:len(manifest_other.parts)] == manifest_other.parts)
PY
printf '%s\n' '--- graph path origins ---'
sed -n '72,165p' src/code/workspace_graph.rsRepository: getappz/agentflare
Length of output: 31521
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- code impact CLI path inputs ---'
fd -i 'code.rs|mod.rs' src/cli src/code --type f -x sh -c 'echo "--- $1"; rg -n -C 8 "impact_for_path|PathBuf|target|repo_root|current_dir" "$1"' sh {}
printf '%s\n' '--- all direct callers ---'
rg -n -C 8 'impact_for_path' --glob '*.rs' .
printf '%s\n' '--- Cargo metadata path assumptions in repository text ---'
rg -n -C 5 'manifest_path|src_path|cargo metadata|repo_root' src/code tests/code_impact_test.rsRepository: getappz/agentflare
Length of output: 6901
Normalize absolute_target before resolving its owner.
Path::starts_with is lexical, so crates/jobs/../../outside.rs still matches crates/jobs and can produce a false impact report. Use lexical normalization instead of canonicalize, which fails for nonexistent targets. Add a regression test.
🤖 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/code/mod.rs` around lines 47 - 54, Normalize the path assigned to
absolute_target before passing it to graph.resolve_owner_crate, using lexical
normalization rather than canonicalize so nonexistent targets remain supported.
Ensure traversal segments such as “..” cannot falsely remain under the workspace
prefix, and add a regression test covering a target that escapes its apparent
crate directory.
| struct MetaDep { | ||
| pkg: String, | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
For Cargo metadata format version 1, how are renamed dependencies represented in resolve.nodes[].deps, and does the name field identify the Rust import crate name?
💡 Result:
In Cargo metadata format version 1, renamed dependencies are represented within the resolve.nodes[].deps array [1][2]. The resolve.nodes[].deps field is an array of objects that provides detailed information about a node's dependencies, serving as an alternative to the simpler dependencies field (which only lists opaque PackageId strings and does not support renamed dependencies) [3][1][2]. Each object in the deps array contains a name field, which explicitly holds the name by which the dependency is imported (the "extern crate" name) [4][1][2]. Yes, the name field identifies the Rust import crate name [4]. Specifically: - If a dependency has been renamed (e.g., using package = "..." in Cargo.toml), the name field contains the new, renamed name rather than the original package name [1][2]. - If the dependency has not been renamed, it contains the default library target name (often the package name with hyphens replaced by underscores) [4][1]. As such, this name field reflects the identifier that should be used in Rust code (e.g., extern crate ...; or in use ...; statements) to refer to that dependency [4]. Note that this name is the library target name, not the package's registration name [4][1].
Citations:
- 1: https://docs.rs/cargo_metadata/^0/struct.NodeDep.html
- 2: https://rust.googlesource.com/rust-lang/cargo/+show/refs/tags/0.84.0/src/doc/man/cargo-metadata.md
- 3: https://docs.rs/cargo_metadata/^0/struct.Node.html
- 4: Include more information about dependencies in Cargo metadata rust-lang/cargo#5583
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' 'lean-ctx availability:'
command -v ctx_search || true
command -v ctx_read || true
command -v ctx_callgraph || true
command -v ctx_compose || true
command -v ctx_shell || true
printf '%s\n' 'Relevant files:'
git ls-files 'src/code/workspace_graph.rs' 'src/code/mod.rs' 'tests/code_impact_test.rs' 'Cargo.toml'
printf '%s\n' 'workspace_graph.rs outline/context:'
if command -v ast-grep >/dev/null 2>&1; then
ast-grep outline src/code/workspace_graph.rs || true
fi
sed -n '1,180p' src/code/workspace_graph.rs
printf '%s\n' 'mod.rs relevant context:'
sed -n '1,150p' src/code/mod.rs
printf '%s\n' 'impact test context:'
sed -n '1,140p' tests/code_impact_test.rsRepository: getappz/agentflare
Length of output: 15967
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' 'MetaDep and graph API usages:'
rg -n -C 3 'MetaDep|reverse_dependents|crate_ident|search_crate_dir' src tests
printf '%s\n' 'Remaining workspace_graph.rs tests:'
sed -n '150,300p' src/code/workspace_graph.rs
printf '%s\n' 'Confirmation search implementation:'
fd -i -t f 'confirm' src
confirm_file="$(fd -i -t f 'confirm' src | head -n 1)"
if [ -n "${confirm_file}" ]; then
sed -n '1,220p' "$confirm_file"
fi
printf '%s\n' 'Synthetic Cargo metadata probe:'
python3 - <<'PY'
import json
metadata = {
"packages": [
{"id": "path+file:///jobs#0.1.0", "name": "jobs"},
{"id": "path+file:///app#0.1.0", "name": "app"},
],
"workspace_members": [
"path+file:///jobs#0.1.0",
"path+file:///app#0.1.0",
],
"resolve": {"nodes": [
{"id": "path+file:///jobs#0.1.0", "deps": []},
{"id": "path+file:///app#0.1.0", "deps": [
{"name": "jobs_alias", "pkg": "path+file:///jobs#0.1.0",
"dep_kinds": [{"kind": None, "target": None}]}
]},
]},
}
node = next(n for n in metadata["resolve"]["nodes"] if n["id"].endswith("/app#0.1.0"))
dep = node["deps"][0]
print("dependency package:", dep["pkg"])
print("dependency import name:", dep["name"])
print("current search identifier:", "jobs".replace("-", "_"))
print("alias search identifier:", dep["name"].replace("-", "_"))
print("current search finds alias reference:", "jobs_alias::Supervisor".find("jobs") >= 0)
print("alias search finds alias reference:", "jobs_alias::Supervisor".find(dep["name"]) >= 0)
PYRepository: getappz/agentflare
Length of output: 15654
🏁 Script executed:
#!/bin/bash
set -eu
python3 - <<'PY'
import json
import re
metadata = {
"packages": [
{"id": "path+file:///jobs#0.1.0", "name": "jobs"},
{"id": "path+file:///app#0.1.0", "name": "app"},
],
"workspace_members": [
"path+file:///jobs#0.1.0",
"path+file:///app#0.1.0",
],
"resolve": {"nodes": [
{"id": "path+file:///jobs#0.1.0", "deps": []},
{"id": "path+file:///app#0.1.0", "deps": [
{"name": "jobs_alias", "pkg": "path+file:///jobs#0.1.0",
"dep_kinds": [{"kind": None, "target": None}]}
]},
]},
}
package_names = {p["id"]: p["name"] for p in metadata["packages"]}
owner = "jobs"
node = next(n for n in metadata["resolve"]["nodes"]
if package_names[n["id"]] == "app")
dep = next(d for d in node["deps"] if package_names[d["pkg"]] == owner)
source_line = "use jobs_alias::Supervisor;"
current_ident = owner.replace("-", "_")
alias_ident = dep["name"].replace("-", "_")
current_pattern = re.compile(r"\b" + re.escape(current_ident) + r"::")
alias_pattern = re.compile(r"\b" + re.escape(alias_ident) + r"::")
print("metadata deps.name:", dep["name"])
print("current confirm pattern:", current_pattern.pattern)
print("alias confirm pattern:", alias_pattern.pattern)
print("current pattern matches source:", bool(current_pattern.search(source_line)))
print("alias pattern matches source:", bool(alias_pattern.search(source_line)))
assert not current_pattern.search(source_line)
assert alias_pattern.search(source_line)
PYRepository: getappz/agentflare
Length of output: 332
Preserve Cargo dependency aliases for reference confirmation.
resolve.nodes[].deps[].name stores the dependency import name. The graph discards this field and searches only owner.name, so use jobs_alias::Supervisor; is not reported for jobs_alias = { package = "jobs", ... }.
src/code/workspace_graph.rs#L68-L70: Retain each dependencynamewith its package ID and dependent crate.src/code/mod.rs#L86-L95: Search each dependent's import name, normalized for Rust identifiers.tests/code_impact_test.rs#L65-L91: Add a renamed-dependency fixture and assert that its reference is reported.
📍 Affects 3 files
src/code/workspace_graph.rs#L68-L70(this comment)src/code/mod.rs#L86-L95tests/code_impact_test.rs#L65-L91
🤖 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/code/workspace_graph.rs` around lines 68 - 70, Preserve Cargo dependency
aliases throughout reference analysis: in src/code/workspace_graph.rs lines
68-70, extend MetaDep and graph construction to retain each dependency name
alongside its package ID and dependent crate; in src/code/mod.rs lines 86-95,
search using each dependent’s normalized Rust import name rather than only
owner.name; in tests/code_impact_test.rs lines 65-91, add a renamed-dependency
fixture and assert the aliased import reference is reported.
Adds post-commit to the installed hook set (.githooks/, HOOKS in src/cli/git.rs): runs `lean-ctx index build` + `lean-ctx graph build` detached in the background after every commit, fail-open if lean-ctx isn't on PATH. Keeps ctx_search/ctx_callgraph and agentflare code impact's reference confirmation from running against a stale graph, without a watcher process or new infra.
Closes the gap surfaced this session: PR #397's own existence was undiscoverable except via git/gh archaeology across branches, because nothing wrote it to memory. `agentflare git ship` now calls memory::mcp::handle_remember after the PR is created/found (topic_key pr-<number>, so a re-run updates rather than duplicates), so a later session can `memory recall` what shipped instead of re-discovering it. Best-effort: a remember failure only warns, never fails an already- successful ship.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 @.githooks/post-commit:
- Line 19: Update the post-commit refresh command to avoid invoking lean-ctx
graph build redundantly or concurrently with lean-ctx index build. Use the
single atomic index refresh path, or chain separate builds with &&, and preserve
failure information in a durable diagnostic instead of discarding statuses
through background redirection.
In `@src/cli/git.rs`:
- Around line 1007-1008: Update the content construction near default_pr_body so
it always explicitly includes the exact commit range {base}..{head}, regardless
of whether the log contains commit subjects or uses the empty-log fallback.
Preserve the existing PR URL in the persisted content.
🪄 Autofix
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
Run ID: 986b1661-075c-4349-85d9-1e0dd2263bbe
📒 Files selected for processing (2)
.githooks/post-commitsrc/cli/git.rs
| # copy under ~/.agentflare/githooks/). | ||
|
|
||
| if command -v lean-ctx >/dev/null 2>&1; then | ||
| ( lean-ctx index build >/dev/null 2>&1; lean-ctx graph build >/dev/null 2>&1 ) & |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- .githooks/post-commit ---'
cat -n .githooks/post-commit
printf '%s\n' '--- lean-ctx references ---'
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
'lean-ctx|index build|graph build' .Repository: getappz/agentflare
Length of output: 20312
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- integration guidance ---'
cat -n AGENTS.md | sed -n '31,60p'
cat -n src/cli/git.rs | sed -n '410,445p'
printf '%s\n' '--- hook installation and canonical-copy references ---'
rg -n -C 5 --hidden \
'post-commit|githooks|canonical|code index refresh' \
src .githooks README.md docs-site AGENTS.md
printf '%s\n' '--- upstream lean-ctx command references ---'
curl -L --fail --silent --show-error \
https://api.github.com/repos/yvgude/lean-ctx/contents \
| jq -r '.[].name' | head -80Repository: getappz/agentflare
Length of output: 23130
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- upstream documentation ---'
for path in README.md LEAN-CTX.md ARCHITECTURE.md; do
printf '\n### %s\n' "$path"
curl -L --fail --silent --show-error \
"https://raw.githubusercontent.com/yvgude/lean-ctx/main/$path" \
| rg -n -i -C 4 'index build|graph build|call.?graph|atomic|generation|refresh' || true
done
printf '%s\n' '--- upstream source paths related to index and graph ---'
curl -L --fail --silent --show-error \
'https://api.github.com/repos/yvgude/lean-ctx/git/trees/main?recursive=1' \
| jq -r '.tree[] | select(.type == "blob") | .path' \
| rg -i '(^|/)(index|graph|call.?graph)|index|graph' \
| head -160Repository: getappz/agentflare
Length of output: 10416
🏁 Script executed:
#!/bin/bash
set -eu
base='https://raw.githubusercontent.com/yvgude/lean-ctx/main'
for path in rust/src/cli/index_cmd.rs rust/src/cli/mod.rs rust/src/tools/ctx_index.rs rust/src/tools/ctx_graph.rs rust/src/core/index_orchestrator.rs rust/src/core/graph_coordinator.rs rust/src/core/index_paths.rs rust/src/core/index_bundle.rs; do
printf '\n--- %s ---\n' "$path"
curl -L --fail --silent --show-error "$base/$path" \
| rg -n -i -C 5 'Build|build|snapshot|generation|atomic|rename|lock|graph' \
| head -220 || true
done
printf '\n--- exact command declarations and dispatch references ---\n'
curl -L --fail --silent --show-error \
'https://api.github.com/repos/yvgude/lean-ctx/git/trees/main?recursive=1' \
| jq -r '.tree[] | select(.type == "blob") | .path' \
| rg 'rust/src/cli|rust/src/tools' \
| while read -r path; do
content="$(curl -L --fail --silent --show-error "$base/$path" || true)"
if printf '%s' "$content" | rg -q -i 'graph build|index build|Build'; then
printf '%s\n' "$path"
printf '%s' "$content" | rg -n -i -C 2 'graph build|index build|Build' | head -60
fi
doneRepository: getappz/agentflare
Length of output: 50375
🏁 Script executed:
#!/bin/bash
set -eu
base='https://raw.githubusercontent.com/yvgude/lean-ctx/main'
printf '%s\n' '--- graph build command ---'
curl -L --fail --silent --show-error \
"$base/rust/src/cli/dispatch/analytics/graph.rs" \
| sed -n '1,115p'
printf '%s\n' '--- index orchestration build entry points ---'
curl -L --fail --silent --show-error \
"$base/rust/src/core/index_orchestrator.rs" \
| sed -n '250,520p'
printf '%s\n' '--- graph index scan and persistence ---'
curl -L --fail --silent --show-error \
"$base/rust/src/core/graph_index/mod.rs" \
| rg -n -C 8 'pub fn scan|fn scan|save|persist|rename|lock|ProjectIndex'
printf '%s\n' '--- deterministic shell sequencing probe ---'
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
cat >"$tmpdir/fake-lean-ctx" <<'EOF'
#!/usr/bin/env bash
if [[ "$*" == "index build" ]]; then
printf '%s\n' index >>"$LOG"
exit 7
fi
if [[ "$*" == "graph build" ]]; then
printf '%s\n' graph >>"$LOG"
exit 0
fi
exit 99
EOF
chmod +x "$tmpdir/fake-lean-ctx"
export PATH="$tmpdir:$PATH" LOG="$tmpdir/log"
( lean-ctx index build >/dev/null 2>&1; lean-ctx graph build >/dev/null 2>&1 )
printf 'semicolon_status=%s commands=%s\n' "$?" "$(paste -sd, "$tmpdir/log")"
: >"$tmpdir/log"
( lean-ctx index build >/dev/null 2>&1 && lean-ctx graph build >/dev/null 2>&1 ) || true
printf 'and_status=%s commands=%s\n' "$?" "$(paste -sd, "$tmpdir/log")"Repository: getappz/agentflare
Length of output: 34038
🏁 Script executed:
#!/bin/bash
set -eu
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
cat >"$tmpdir/lean-ctx" <<'EOF'
#!/usr/bin/env bash
if [[ "$*" == "index build" ]]; then
printf '%s\n' index >>"$LOG"
exit 7
fi
if [[ "$*" == "graph build" ]]; then
printf '%s\n' graph >>"$LOG"
exit 0
fi
exit 99
EOF
chmod +x "$tmpdir/lean-ctx"
export PATH="$tmpdir:$PATH" LOG="$tmpdir/log"
set +e
( lean-ctx index build >/dev/null 2>&1; lean-ctx graph build >/dev/null 2>&1 )
semicolon_status=$?
semicolon_commands="$(paste -sd, "$tmpdir/log")"
: >"$tmpdir/log"
( lean-ctx index build >/dev/null 2>&1 && lean-ctx graph build >/dev/null 2>&1 )
and_status=$?
and_commands="$(paste -sd, "$tmpdir/log")"
set -e
printf 'semicolon_status=%s commands=%s\n' "$semicolon_status" "$semicolon_commands"
printf 'and_status=%s commands=%s\n' "$and_status" "$and_commands"Repository: getappz/agentflare
Length of output: 288
Serialize the code-index refresh and record failures.
lean-ctx index build already builds the graph and BM25 indexes. Running lean-ctx graph build separately can race with that graph build. The ; also runs it after an index failure, while redirected statuses make the background refresh report success. Use one atomic refresh path, or chain separate commands with && and write failures to a durable diagnostic.
🤖 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 @.githooks/post-commit at line 19, Update the post-commit refresh command to
avoid invoking lean-ctx graph build redundantly or concurrently with lean-ctx
index build. Use the single atomic index refresh path, or chain separate builds
with &&, and preserve failure information in a durable diagnostic instead of
discarding statuses through background redirection.
| let log = default_pr_body(repo_root, base, head); | ||
| let content = format!("{log}\n\n{}", pr.html_url); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Persist the exact commit range.
When default_pr_body returns commit subjects, it does not include base or head. Only the empty-log fallback contains the range. The memory record then cannot identify the exact shipped range. Include {base}..{head} explicitly in content.
Proposed fix
let log = default_pr_body(repo_root, base, head);
- let content = format!("{log}\n\n{}", pr.html_url);
+ let content = format!(
+ "Commit range: {base}..{head}\n\n{log}\n\n{}",
+ pr.html_url
+ );📝 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.
| let log = default_pr_body(repo_root, base, head); | |
| let content = format!("{log}\n\n{}", pr.html_url); | |
| let log = default_pr_body(repo_root, base, head); | |
| let content = format!( | |
| "Commit range: {base}..{head}\n\n{log}\n\n{}", | |
| pr.html_url | |
| ); |
🤖 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/git.rs` around lines 1007 - 1008, Update the content construction
near default_pr_body so it always explicitly includes the exact commit range
{base}..{head}, regardless of whether the log contains commit subjects or uses
the empty-log fallback. Preserve the existing PR URL in the persisted content.
CI's rustfmt (1.97.1) collapses this fs::write call onto one line; local default toolchain was 1.97.0, which didn't flag it -- a rustfmt patch-version formatting difference, not new code. Fixes the fmt/CI Green failures blocking #397.
Summary
agentflare code impact <path>command: accurate Rust cross-crate blast-radius / test-impact analysis for Cargo workspaces.crates/agentflare-jobs/tests/supervisor_test.rs'suse agentflare_jobs::{Supervisor}produced no edge tosupervisor.rsat all).cargo metadatafor the authoritative crate graph (including dev-dependencies, so integration tests show up as dependents) plus ause <crate>::regex confirmation pass (preferring thelean-ctxCLI when installed, falling back to a built-in scan) — no new indexing system.Test plan
WorkspaceGraphparsing/resolution,confirmmodule's lean-ctx-output parser and fallback scanneragentflare code impact crates/agentflare-jobs/src/supervisor.rscorrectly reportssupervisor_test.rs,queue_test.rs,worker_test.rsas dependents, with no duplicatesSummary by CodeRabbit
code impactcommand to identify tests and dependent code affected by a target file.