Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2e42bdc
fix: recommend sub-agent dispatch for large-scope lifting (v0.8.3)
userFRM Apr 14, 2026
939e8e6
address Codex audit: single-line NEXT STEP, live config, runtime-neutral
userFRM Apr 14, 2026
c3eefa6
docs: "RPG first" — counter the grep/cat/Read reflex across every sur…
userFRM Apr 14, 2026
1b045b8
address Opus audit (H1 + 3 LOW): fabricated metric, runtime-neutral p…
userFRM Apr 14, 2026
99e9416
fix: address Codex round 2 — CLI reload, config refresh, hedged dispatch
userFRM Apr 14, 2026
3eea0bc
fix: address Codex round 3 — reload after delegation, reload_rpg refr…
userFRM Apr 14, 2026
a981fc9
feat: drift maintenance — auto-sync notice now actively prescribes re…
userFRM Apr 14, 2026
bd3f7c6
fix: address Codex round 4 — drift labeling, finalize_lifting timing,…
userFRM Apr 14, 2026
f176b28
fix: address Codex round 5 — stale-feature drift now drives lifting_s…
userFRM Apr 14, 2026
5f75575
fix: drain stale_entity_ids when auto-lift re-writes a stale entity
userFRM Apr 14, 2026
295de14
fix: stale-tracking coverage gaps + CHANGELOG format
userFRM Apr 14, 2026
0cc43c3
feat: nudge lifting on build_rpg + doc lock order + cache-friendly pr…
userFRM Apr 14, 2026
a4b84af
fix: deadlock cycle in build_semantic_hierarchy + module-count mismat…
userFRM Apr 14, 2026
d0fb97e
fix: close TOCTOU in build_semantic_hierarchy install + rename "lifte…
userFRM Apr 14, 2026
c51a1a6
fix: session-clear TOCTOU in batch-0 + project-switch config contamin…
userFRM Apr 14, 2026
26a2715
fix: collapse build_semantic_hierarchy init into single write-lock ac…
userFRM Apr 14, 2026
86d455f
fix: pass graph through hierarchy helpers + prune stale on reload
userFRM Apr 14, 2026
4d76e87
fix: independent-audit findings (startup stale loss + auto_lift drain…
userFRM Apr 14, 2026
816b678
polish: close remaining LOW findings from second independent audit
userFRM Apr 14, 2026
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
31 changes: 29 additions & 2 deletions .claude/skills/rpg/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
---
name: rpg
description: 'Build and query semantic code graphs using RPG-Encoder. Use when the user wants to understand codebase structure, search for code by intent, explore dependencies, analyze change impact, or perform semantic lifting.'
description: 'Build and query semantic code graphs using RPG-Encoder. Use BEFORE grep/cat/find for any question about code structure, behavior, relationships, impact, dependencies, or cross-file patterns.'
allowed-tools: Bash(rpg-encoder *), Read, Glob, Grep
---

# RPG-Encoder CLI Skill
# RPG-Encoder — USE BEFORE grep/cat/find

## Reach for RPG first, shell commands second

Whenever the user asks about code structure, behavior, relationships, impact,
dependencies, or cross-file patterns, reach for RPG commands BEFORE falling
back to `grep`, `cat`, `find`, `wc`, or `Read`. RPG is indexed, semantically
organized, and answers structural questions in one call that would otherwise
require dozens of chained text searches.

| If you'd otherwise... | Use this instead |
|---|---|
| `grep -r` by intent | `rpg-encoder search "describe what it does"` |
| `grep -r` by name | `rpg-encoder search "name" --mode snippets` |
| `cat file` for a function | `rpg-encoder fetch "file:func"` |
| chained greps for callers | `rpg-encoder explore ENTITY --direction up` |
| chained greps for callees | `rpg-encoder explore ENTITY --direction down` |
| `wc -l` / `find` / `tree` | `rpg-encoder info` |
| reading many files | Use the MCP `semantic_snapshot` tool if available |

Fall back to `grep` / `cat` / `Read` only when the query is about literal text
(string search, comments, TODOs, log messages) — not structure or semantics.

If you have the RPG MCP server connected, prefer its tools (`search_node`,
`fetch_node`, `explore_rpg`, `impact_radius`, `plan_change`, `semantic_snapshot`,
`context_pack`) over the CLI — they're faster and return structured data.

---

You have access to `rpg-encoder`, a CLI tool that builds semantic code graphs (Repository Planning Graphs) from any codebase. Use it to understand code structure, search by intent, trace dependencies, and perform autonomous semantic lifting.

Expand Down
13 changes: 13 additions & 0 deletions .gemini/extensions/rpg/CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

RPG-Encoder builds semantic code graphs (Repository Planning Graphs) for AI-assisted code understanding.

## Use RPG before grep / cat / find

For any question about code structure, behavior, relationships, impact, or
cross-file patterns, reach for RPG tools (MCP or CLI) before shell commands.
RPG answers structural questions in one call that would otherwise require
dozens of chained text searches.

Fall back to grep / cat / file reads only when the query is about literal
text (string search, comments, TODOs, log messages).

See the MCP server instructions for the full mapping of shell patterns to
RPG tools — it's loaded automatically when the extension is active.

## CLI Commands

- `rpg-encoder build` — Index codebase, build graph (run once)
Expand Down
2 changes: 1 addition & 1 deletion .gemini/extensions/rpg/commands/rpg-lift.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ The lift pipeline:

Progress is saved after each batch. If interrupted, re-running continues from where it stopped.

After completion, run `rpg-encoder info` to show the updated graph statistics.
After completion, run `rpg-encoder info` to show the updated graph statistics. If an MCP RPG server is currently connected to your editor, also call its `reload_rpg` tool so it picks up the new graph from disk.
"""
2 changes: 1 addition & 1 deletion .gemini/extensions/rpg/gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rpg-encoder",
"version": "0.8.2",
"version": "0.8.3",
"description": "Build and query semantic code graphs (Repository Planning Graphs) for AI-assisted code understanding. Provides entity search, dependency exploration, and autonomous LLM-driven semantic lifting.",
"mcpServers": {
"rpg-encoder": {
Expand Down
179 changes: 179 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,185 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [0.8.3] - 2026-04-14

### Added

- `lifting_status` now tracks stale-feature drift across calls. A
persistent per-server set records entities whose source was modified
after they were lifted; the dashboard reports `stale_features: N
entities modified since last lift` and the NEXT STEP state machine
prompts re-lift even when coverage is 100%.
- `get_entities_for_lifting(scope="*")` now returns stale entities
alongside unlifted ones, so a single call covers both "never lifted"
and "lifted-but-outdated" work.
- `lifting_status` emits a sub-agent dispatch recommendation when the
remaining work (unlifted + stale) is ≥100 entities. The response
contains `LOOP` / `DISPATCH` / `FALLBACK` blocks so callers delegate
directly without first loading a batch of source into their own
context.
- `get_entities_for_lifting` batch-0 emits a one-line dispatch hint
when ≥10 token-aware batches are queued, pointing back to
`lifting_status` for the full recommendation.
- `submit_lift_results` NEXT action is now scale-aware — when remaining
work ≥100 entities, it redirects the caller to `lifting_status`
instead of encouraging another foreground batch.
- `build_rpg` response now emits an action-oriented NEXT STEP directing
the agent to lift immediately. Small scope lifts inline; large scope
dispatches a sub-agent with the LOOP pattern embedded.
- New `USE RPG FIRST` top section in `server_instructions.md` with a
mapping table from shell patterns (`grep -r`, `cat`, `find`, `wc -l`,
chained greps) to the RPG tool that replaces them.
- New `DRIFT MAINTENANCE` section in `server_instructions.md`
explaining the three auto-sync notice variants and framing re-lift
as part of definition-of-done for any task that wrote code.
- Tool descriptions for `search_node`, `fetch_node`, `explore_rpg`,
`rpg_info`, `semantic_snapshot`, `context_pack`, `impact_radius`,
`plan_change`, `analyze_health`, `detect_cycles`, `find_paths`, and
`slice_between` now open with a `PREFER THIS OVER ...` marker naming
the shell command or workflow they replace.
- `.claude/skills/rpg/SKILL.md` and `README.md` carry the same
RPG-first mapping table as the server prompt.
- Crate-visible `LARGE_SCOPE_ENTITIES` (100) and `LARGE_SCOPE_BATCHES`
(10) constants replace duplicated magic numbers across
`server.rs`/`tools.rs` with doc comments describing the
heuristic-vs-authoritative relationship.
- Canonical lock-order invariant documented on the `RpgServer` struct
so reviewers don't have to re-derive it from scattered call sites.
- `reload_config_with_warning` helper on `RpgServer` that distinguishes
missing `.rpg/config.toml` (silent default) from malformed TOML
(stderr warning, keeps previous in-memory config).

### Changed

- `lifting_status` NEXT STEP is runtime-neutral. No specific runtime's
dispatch syntax appears in the response; callers use whatever
sub-agent or cheaper-model mechanism their runtime exposes. Explicit
fallbacks: scoped lifting for callers with no delegation mechanism,
and `rpg-encoder lift --provider anthropic|openai` for callers with
an API key and no sub-agent support.
- Batch-size estimates in NEXT STEP messages read from the live
`encoding.max_batch_tokens` config instead of a hard-coded `~12K`
figure, so the estimate scales when the user overrides the budget.
- `NEXT STEP:` remains a single parseable line; dispatch detail is
emitted in labeled blocks immediately below.
- Auto-sync notice now prescribes a verb: it distinguishes per-update
delta from pre-existing backlog and separates new-entity drift from
stale-feature drift, so an agent that commits code and sees the
notice is told to re-lift rather than informed of a count.
- CLI fallback in large-scope guidance is gated to cases with actual
unlifted work, with a note that `rpg-encoder lift` does not re-lift
stale entities (it filters to entities with no features).
- `get_routing_candidates` response header no longer includes the
graph revision hash — it moved to the NEXT_ACTION block at the
bottom. Keeps the stable preamble (instructions + entity table)
cache-eligible while still surfacing the revision where the agent
needs to read it back.
- `server_instructions.md` LIFTING FLOW sub-section rewritten and
shortened.
- `set_project_root` on project switch now loads the new project's
`.rpg/config.toml` independently; on parse failure it falls back to
`RpgConfig::default()` rather than preserving the previous project's
config. Same-project `reload_rpg` preserves the previous config on
parse failure (different flow, different correctness requirement).

### Fixed

- `lifting_status` previously reported `Graph is complete` as soon as
every entity had some features, ignoring stale features from
modified sources. The state machine now considers
`remaining + stale_features` combined.
- `get_entities_for_lifting(scope="*")` previously returned zero
entities when all drift was stale (features present, sources
modified) because `resolve_scope` filters to entities with no
features. It now augments the resolved scope with tracked stale
entities and routes them through the LLM loop.
- Auto-sync notice previously conflated per-update delta with global
backlog, so a one-line edit on a partially-lifted repo could claim
"50 new entities unlifted" when only 1 was actually new.
- `finalize_lifting` fallback guidance previously said to call it
after each scoped subtree. That auto-routes pending entities
against incomplete signals and locks the hierarchy early. Guidance
now says to call `finalize_lifting` once after all scopes complete.
- `rpg-encoder lift --provider ...` (CLI fallback) left the MCP
server on a stale in-memory graph. All docs that mention the CLI
fallback now specify that the caller must call `reload_rpg`
afterward.
- `set_project_root` and `reload_rpg` previously used
`unwrap_or_default()` on config loads, collapsing missing-config
and malformed-TOML into identical silent behavior.
- `set_project_root` failed to refresh `self.config` on project
switch; the server kept serving the previous project's encoding
settings.
- `lifting_status` large-scope recommendation previously ran off raw
unlifted count, before auto-lift had reduced the set. On repos full
of trivial entities (getters, setters, constructors) it could
recommend delegation for ~0 LLM calls. The large-scope branch now
signals likely-large and defers the authoritative check to the
post-auto-lift batch count in `get_entities_for_lifting`.
- `rpg_info` error wording ("No RPG found") was miscited as a
friendly status string; corrected to "any RPG tool returns 'No RPG
found'".
- `build_rpg` NEXT STEP and `lifted: X/Y` header previously counted
`Module` entities against the unlifted total, while
`lifting_status` and `get_entities_for_lifting` exclude them. The
two could disagree by hundreds of entities on large codebases,
tripping the delegation threshold in `build_rpg` when
`lifting_status` would still recommend foreground lifting. Both
paths now use `lifting_coverage()` (non-module) for the count, and
the header reads `liftable_entities: X/Y`.
- `submit_lift_results` previously emitted `DONE` as soon as coverage
reached 100%, which could terminate a stale-only re-lift loop after
batch 1 while later batches were still queued. The NEXT/DONE
branch now counts unlifted + stale remaining.
- `update_rpg` now feeds `summary.modified_entity_ids` into the
stale-tracking set so its `needs_relift: N` reply aligns with what
`lifting_status` and `get_entities_for_lifting(scope="*")` report.
- Server startup auto-update now feeds `modified_entity_ids` into
the stale-tracking set and seeds the auto-sync changeset hash for a
clean workdir. Previously modifications between the last lift and
a session restart silently dropped off the dashboard.
- `auto_lift` on a non-`*` scope now drains stale entries for every
in-scope entity. The pipeline freshens features for each
regardless of existing state, so stale markers for those IDs are
invalid after the call; the unconditional drain also handles the
identical-features case where a cosmetic edit re-lifts to the
same output.
- Auto-lifted features for entities previously flagged stale now
drain the stale-tracking set inline in
`get_entities_for_lifting`, so the count doesn't inflate when the
auto-lifter writes fresh features directly.
- `reload_rpg` now prunes the stale-tracking set against the newly
loaded graph rather than clearing it wholesale. The CLI / isolated
sub-agent re-lift flow only refreshes entities with no features —
stale entities survive it, so clearing would let `lifting_status`
report 100% coverage while re-lift work remained.
- `reload_rpg` drift-tracking reset now sits on the success path,
after `storage::load` returns `Ok`. Transient read errors no longer
wipe the backlog while leaving the previous graph in memory.
- `build_rpg` now prunes the stale-tracking set against the newly
built graph so dead entity IDs don't accumulate across rebuilds.
- `build_semantic_hierarchy` sharded init no longer acquires
`hierarchy_session.write()` before `graph.read()`. The original
order formed a deadlock cycle with `update_rpg`'s
graph-then-session order under concurrent scheduling. The init
path now collapses decision + snapshot into a single
`hierarchy_session.write()` held under `graph.read()` and packages
the work into an `Action` enum so there's no peek-then-trust.
- `build_batch_0_domain_discovery` and `build_cluster_batch` now take
`&RPGraph` and (where applicable) clusters as parameters instead
of re-reading `self.graph` / `self.hierarchy_session`. Closes two
TOCTOU windows: a session-clear race where a concurrent
`build_rpg`/`update_rpg` could panic on `session.as_mut().unwrap()`,
and a graph-replace race where a concurrent `set_project_root`
could panic on `graph.as_ref().unwrap()`.
- `set_project_root` tool description is no longer Claude-Code-specific
in its example; reads runtime-neutral.
- `get_entities_for_lifting` batch-0 dispatch NOTE no longer
references "batches 2..N" (off-by-one against the 0-based
`batch_index` parameter). Reads "do not request further batches in
this context".

## [0.8.2] - 2026-04-14

### Added
Expand Down
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ members = [
]

[workspace.package]
version = "0.8.2"
version = "0.8.3"
edition = "2024"
license = "MIT"
authors = ["userFRM"]
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Then open any repo and tell your agent:

Your agent handles everything: indexes entities (seconds), reads each function and adds intent-level features (a few minutes), organizes them into a semantic hierarchy, and commits `.rpg/graph.json` for your team.

For repos with ~100+ entities, `lifting_status` will tell your agent to delegate the lifting loop to a sub-agent or a cheaper model — feature extraction is pattern-matching, not novel reasoning. If your runtime has no sub-agent mechanism, run `rpg-encoder lift --provider anthropic|openai` from the terminal with an API key — the CLI drives an external LLM directly with no agent involvement. After the CLI finishes, call `reload_rpg` in your session to load the updated graph. The CLI lifts entities with no features; re-lifting stale entities (features present but outdated after code changes) is handled by the in-session MCP flow, not the CLI.

Once lifted, try:

- *"What handles authentication?"* — finds code even when nothing is named "auth"
Expand All @@ -45,6 +47,30 @@ Once lifted, try:

---

## Use RPG before `grep`, `cat`, `find`

The server instructions tell your agent to reach for RPG tools FIRST for any
question about code structure or behavior. That reflex matters — `grep`, `cat`,
and ad-hoc file reads burn tokens and miss semantic relationships RPG already
knows.

| If you'd otherwise reach for... | Use this instead |
|---|---|
| `grep -r` / `rg` (by intent) | `search_node(query="...")` |
| `grep -r` / `rg` (by name) | `search_node(query="...", mode="snippets")` |
| `cat` / reading a function | `fetch_node(entity_id="file:name")` |
| chained greps for callers/callees | `explore_rpg(entity_id="...", direction="...")` |
| recursive grep for "what depends on X" | `impact_radius(entity_id="...")` |
| `wc -l` / `find` / `tree` | `rpg_info` |
| reading many files for context | `semantic_snapshot` |
| manual search → fetch → explore chains | `context_pack(query="...")` |
| "how do I refactor X safely" | `plan_change(goal="...")` |

Fall back to `grep`, `cat`, or file reads only when the query is about literal text
(string search, comments, TODOs, log messages) — not about structure.

---

## How It Works

<p align="center">
Expand Down
Loading
Loading