Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 0 additions & 50 deletions .agents/AGENTS.md

This file was deleted.

99 changes: 99 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# AGENTS.md — CodeGraph

Rust workspace: tree-sitter parse → semantic graph (global symbol ID + call chain) trong `.codegraph/`,
phục vụ AI agent qua MCP; CLI `codegraph`. 15 crate, binary duy nhất.

## Bắt buộc: CodeGraph MCP là công cụ ĐẦU TIÊN

Trước khi grep/read để hiểu code, gọi MCP:

| Câu hỏi | Tool |
|---|---|
| Symbol ở đâu / signature | `codegraph_search_symbol`, `codegraph_symbol` |
| Ai gọi / gọi ai | `codegraph_callers`, `codegraph_callees` |
| Sửa X ảnh hưởng gì | `codegraph_impact` |
| Luồng điều khiển / trace | `codegraph_flow`, `codegraph_trace_full_flow` |
| Tìm theo marker | `codegraph_search_flow` |
| Context gói gọn | `codegraph_context` |
| Review diff | `codegraph_graphcode_diff` |
| Bind / re-index | `codegraph_init` (index mặc định **false**), `codegraph_index` |

- Index là ảnh chụp. Vừa sửa code mà chưa `codegraph_index` → kết quả cũ; đọc file để xác nhận.
- Grep/read vẫn đúng cho: text literal, `docs/`, `config.toml`, file ngoài index.
- Search lớn: `timeout_ms` + retry đúng args kèm `resume`.
- Đừng tin số liệu trong docs (tool count, version, language count) — đọc source.

## Build & verify

```bash
cargo build --workspace
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings # gate CI
cargo fmt --all
```

- Toolchain: `codegraph-graph`, `codegraph-docs`, `codegraph-bench` dùng **edition 2024** → cần Rust ≥ 1.85.
`rust-version = "1.80"` trong `Cargo.toml` là số sai, đừng tin.
- `web/` là UI Svelte (npm) — chỉ cần khi sửa UI: `scripts/build-web.sh` sinh
`crates/codegraph-web/assets/` (không commit) rồi `rust-embed` nhúng lúc compile.
- Binary `codegraph` mà MCP host đang chạy là bản **đã cài**, không phải `target/debug`. Sửa tool surface
(`crates/codegraph-mcp/src/tools.rs`) mà không rebuild/reinstall thì agent vẫn thấy tool cũ.

## Test quirks

- `cargo test -p codegraph` chạy **0 test** — CLI chưa có test. Đừng coi đó là đã verify.
- Backend cần service thật + env:
`TEST_REDIS_DSN=redis://127.0.0.1:6379` (feature `redis`);
`TEST_RDBMS_DSN=...` + `TEST_RDBMS_REPO_ID=1` (feature `postgres`/`mysql`).
Chạy `#[ignore]`: `cargo test -p codegraph-graph --features postgres --test rdbms -- --ignored`.
Lưu ý: 4 test `storage::redis::tests::*` trong `crates/codegraph-graph/src/storage/redis.rs` KHÔNG `#[ignore]`,
hardcode `redis://127.0.0.1:6379/15` → fail `Connection refused` nếu không có redis-server (pre-existing,
không phải port contention). Chạy lại standalone để xác nhận.
- `crates/codegraph-binary/tests/extract.rs` cần `radare2` trên PATH (`--ignored`).
- `crates/codegraph-mcp/src/response_tests.rs` assert số tool đăng ký — thêm/bớt tool phải sửa số đó.
- Test config/flow cần `install_current(...)` và reset `install_current(None)`; classifier là thread-local.

## Quy trình verify + PR (bắt buộc, đúng thứ tự)

1. `cargo fmt --all`
2. `cargo clippy --workspace --all-targets -- -D warnings`
- storage feature-gated: `cargo clippy -p codegraph-graph --features postgres,mysql,redis --tests -- -D warnings`
3. `cargo test --workspace` — **toàn bộ** unit + integration (không dùng `--lib` để kết luận)
4. Regression đúng vùng vừa sửa:
- extract/config/marker → `cargo test -p codegraph-extract --test effects_config --test chains --test dynamic_dispatch`
- trace/sandbox → `cargo test -p codegraph-graph --test trace_flow_tests` + `cargo test -p codegraph-sboxes`
- backend → `cargo test -p codegraph-graph --features sqlite,lmdb`
- lưu ý: 4 test `storage::redis` fail khi chạy song song toàn workspace (port contention, pre-existing) → chạy lại standalone để xác nhận.
5. Tạo nhánh → commit (conventional commits) → mở PR.
6. Chờ GitHub Actions xanh (test matrix + clippy + web build).
7. Chờ review benchmark (Criterion/CodSpeed) và review Codecov — coverage không được giảm.
8. Chỉ merge sau khi 6–7 xanh.

## Gotchas kiến trúc

- Config chỉ có **một bảng** `[[effect_rules]]`: mỗi rule đặt `effect` và/hoặc `marker` (≥1).
`[[flow_rules]]` và `codegraph_config_flow` đã gộp/xoá; key cũ bị bỏ qua + warn.
- `CALL_ENTER` đọc `chain[pos+1]` làm callee → không chèn marker vào giữa `CALL_ENTER…CALL_EXIT`.
- Marker/ID là contract serialize ổn định — không đổi số cũ (`crates/codegraph-core/src/semgraph.rs`).
- `.codegraph/` không commit. `codegraph clean` xoá index nhưng giữ `config.toml`; `deinit` xoá cả thư mục.
- Thêm language: module trong `crates/codegraph-extract/src/languages/` + đăng ký `languages.rs` +
feature `lang-<x>` + fixture/test.

## Nguồn sự thật

| Thứ | File |
|---|---|
| MCP tool + schema | `crates/codegraph-mcp/src/tools.rs` |
| Config + validation | `crates/codegraph-extract/src/config.rs` |
| Marker/ID/type lõi | `crates/codegraph-core/src/semgraph.rs` |
| Parser registry | `crates/codegraph-extract/src/languages.rs` |
| CI thật (feature/service) | `.github/workflows/ci.yml` |

## Chi tiết

- [MCP workflow](docs/agent/mcp-workflow.md)
- [Rust conventions](docs/agent/conventions.md)
- [Testing](docs/agent/testing.md)
- [Extraction & config](docs/agent/extraction.md)
- [Git & release](docs/agent/git-release.md)
- [Architecture](docs/architecture.md) · [Development](docs/development.md) · [Configuration](docs/configuration.md)
16 changes: 8 additions & 8 deletions crates/codegraph-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ pub use route::StorageRoute;
pub use semgraph::{
is_marker, marker_id, marker_name, Annotation, BranchLabel, CallRecord, CallSite,
CallSiteResult, ClassInfo, DbStats as SemgraphStats, DependenciesReport, Dependency,
EffectCallPattern, EffectRule, EffectType, FileInfo, FlowCall, FlowResult, FlowStep,
FullFlowPath, FunctionScope, Marker, MemberInfo, PathEnding, ResolutionKind, ResolveResult,
ScopeLevel, SearchFlowResult, Symbol, SymbolId, SymbolKind, SymbolMatch, TraceAction,
MARKER_AWAIT, MARKER_BRANCH_END, MARKER_BREAK, MARKER_CALL_ENTER, MARKER_CALL_EXIT,
MARKER_CATCH_START, MARKER_CONTINUE, MARKER_DEFER, MARKER_GO, MARKER_IF_FALSE, MARKER_IF_TRUE,
MARKER_LOOP, MARKER_LOOP_BACK, MARKER_REC_CALL, MARKER_RETURN, MARKER_STMT_END,
MARKER_SWITCH_CASE, MARKER_SWITCH_CLOSE, MARKER_SWITCH_END, MARKER_SWITCH_START, MARKER_THROW,
MARKER_TRY_END, MARKER_TRY_START, SYMBOL_BASE,
EffectCallPattern, EffectRule, EffectType, FileInfo, FlowCall, FlowMarker, FlowResult,
FlowStep, FullFlowPath, FunctionScope, Marker, MemberInfo, PathEnding, ResolutionKind,
ResolveResult, ScopeLevel, SearchFlowResult, Symbol, SymbolId, SymbolKind, SymbolMatch,
TraceAction, MARKER_AWAIT, MARKER_BRANCH_END, MARKER_BREAK, MARKER_CALL_ENTER,
MARKER_CALL_EXIT, MARKER_CATCH_START, MARKER_CONTINUE, MARKER_DEFER, MARKER_GO,
MARKER_IF_FALSE, MARKER_IF_TRUE, MARKER_LOOP, MARKER_LOOP_BACK, MARKER_REC_CALL, MARKER_RETURN,
MARKER_STMT_END, MARKER_SWITCH_CASE, MARKER_SWITCH_CLOSE, MARKER_SWITCH_END,
MARKER_SWITCH_START, MARKER_THROW, MARKER_TRY_END, MARKER_TRY_START, SYMBOL_BASE,
};
101 changes: 100 additions & 1 deletion crates/codegraph-core/src/semgraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,112 @@ pub enum EffectCallPattern {
}

/// Một effect rule từ `[[effect_rules]]` trong config.toml.
/// Một rule có thể khai báo `effect`, `marker`, hoặc cả hai (≥1 trong hai):
/// - `effect` — tác động bên ngoài (sql_query, http_call, panic, …).
/// - `marker` — vai trò control-flow (try_start, throw, if_true, …).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EffectRule {
#[serde(rename = "call")]
pub call: EffectCallPattern,
pub effect: EffectType,
/// `None` = rule không khai báo effect (chỉ marker). `Some(None)` vẫn dùng
/// để shadow một bảng default (ví dụ `effect = "none"` chặn default sql_write).
#[serde(default)]
pub effect: Option<EffectType>,
/// Vai trò control-flow (None = rule effect thuần).
#[serde(default)]
pub marker: Option<FlowMarker>,
/// Nhãn exception / nhánh nhánh — hợp lệ với `throw` | `catch_start` | `if_true`.
#[serde(default)]
pub label: Option<String>,
/// `true` → vẫn ghi CallRecord (throw-er là call thật); `false` → chỉ emit
/// marker (macro không phải call thật). Default: throw=true, còn lại=false.
#[serde(default)]
pub keep_call: Option<bool>,
}

impl EffectRule {
/// Default `keep_call` theo marker: `throw` = call thật (giữ CallRecord),
/// các marker khác = macro (chỉ marker).
pub fn keep_call_or_default(&self) -> bool {
self.keep_call
.unwrap_or(self.marker == Some(FlowMarker::Throw))
}
}

/// Marker control-flow mà một flow rule được map vào — whitelist các marker
/// "điều khiển" (`[[effect_rules]]` báo macro/magic call đóng vai trò này).
/// Không cho phép marker call-edge (`CALL_ENTER`/`CALL_EXIT`) → không phá được
/// call graph. Các variant đều đã có sẵn `Marker` (serialization ổn định).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FlowMarker {
/// Mở khối try — interpreter push `catch_stack` tại vị trí này.
TryStart,
/// Đóng khối try gần nhất — pop `catch_stack`.
TryEnd,
/// Handler catch trong khối try; không label → match mọi exception.
CatchStart,
/// Throw — interpreter nhảy tới handler khớp, hoặc unwind lên caller.
Throw,
/// Nhánh nếu-đúng của macro if.
IfTrue,
/// Nhánh nếu-sai / else của macro if.
IfFalse,
/// Đóng khối nhánh của macro if/endif.
BranchEnd,
/// Break của macro loop.
Break,
/// Continue của macro loop.
Continue,
/// Mở loop của macro loop.
Loop,
/// Đóng loop (quay lại LOOP tương ứng).
LoopBack,
/// Return của macro return sớm.
Return,
}

impl FlowMarker {
pub fn as_str(self) -> &'static str {
match self {
Self::TryStart => "try_start",
Self::TryEnd => "try_end",
Self::CatchStart => "catch_start",
Self::Throw => "throw",
Self::IfTrue => "if_true",
Self::IfFalse => "if_false",
Self::BranchEnd => "branch_end",
Self::Break => "break",
Self::Continue => "continue",
Self::Loop => "loop",
Self::LoopBack => "loop_back",
Self::Return => "return",
}
}

/// Parse snake_case (case-insensitive) — chuỗi không biết → `None`.
pub fn parse(s: &str) -> Option<Self> {
Some(match s.trim().to_ascii_lowercase().as_str() {
"try_start" => Self::TryStart,
"try_end" => Self::TryEnd,
"catch_start" => Self::CatchStart,
"throw" => Self::Throw,
"if_true" => Self::IfTrue,
"if_false" => Self::IfFalse,
"branch_end" => Self::BranchEnd,
"break" => Self::Break,
"continue" => Self::Continue,
"loop" => Self::Loop,
"loop_back" => Self::LoopBack,
"return" => Self::Return,
_ => return None,
})
}
}

// Xoá `FlowRule` riêng — logic dùng chung gộp vào `EffectRule` (xem plan
// effect-rules-control-flow-upgrade.md).

// ==================== Entities ====================

/// Id global của symbol (u64, bắt đầu từ `SYMBOL_BASE`).
Expand Down
Loading
Loading