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
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

## Unreleased

- Add deterministic, bounded natural-language routing for symbol search,
callers, callees, impact, and node trails through `compass ask`, clear
`compass query` intents, and MCP `query_graph`. Generic, contradictory,
historical, or explicitly traversed queries retain compatibility traversal,
while ambiguous symbols remain explicit instead of selecting an arbitrary
candidate.

- Hard-cut typed symbol search to the deterministic `query-ranker/2`, add a
23-question executable relevance baseline with reviewed paraphrase,
production-versus-generated ambiguity, domain, and no-answer cases, and add
a bounded local redaction/review workflow for growing the corpus from
approved production query samples without network telemetry or automatic
judgment generation. Opt-in MCP query logs now cover typed natural queries,
use a versioned record, and stop at 16 MiB. Search now enforces
`maxCandidates` as the total recall-pool bound instead of silently inflating
it to `maxNodes`.

- Make `compass upgrade` discover releases through a bounded, versioned static
release manifest instead of the unauthenticated GitHub REST API. Corporate
networks that share an outbound IP no longer consume GitHub's per-IP API
Expand All @@ -13,7 +30,9 @@
re-exports, calls, references, heritage, aliases, and framework route
targets. The candidate is now the same deterministic path used by
qualification fixtures, with universal provenance and cross-file resolution
preserved through cached and rebuilt graphs.
preserved through cached and rebuilt graphs. Preserve the pipeline's exact
repository-relative identity for universal framework facts so shallow source
paths are published instead of being mistaken for temporary-directory paths.

## 0.3.6 - 2026-08-06

Expand Down
22 changes: 22 additions & 0 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,28 @@ and reference are internal realizations of the backend-neutral `compass-store`
contract, not a stable SQL schema or pointer format that consumers may query
directly.

The additive `compass ask` command routes bounded natural-language questions
to the existing typed search, callers, callees, impact, or node-trail operation
and returns the same `compass.query/1` response contract. `compass query`
automatically uses that path for high-confidence questions against a current
typed graph. Generic or contradictory questions, historical `--at` queries,
and requests with `--traverse`, `--dfs`, `--context`, `--budget`, or `--page`
retain the established text-traversal behavior. Explicit typed query commands
remain available and unchanged; ambiguous questions never invent a direction
or select an arbitrary symbol.

Typed symbol search now unconditionally uses `query-ranker/2`. The internal
`COMPASS_QUERY_RANKER_PROFILE` experiment switch and v1 runtime fallback have
been removed. This does not change the `compass.query/1` schema, but intentional
score and ordering improvements can change which equally lexical candidate is
ranked first; ordering remains deterministic and backend-neutral.

Optional MCP query feedback remains local and disabled by default.
`COMPASS_QUERY_LOG=<path>` writes the versioned `compass.query-log/1` JSONL
contract up to a 16 MiB file bound. The review importer accepts only its
bounded `question` field and emits a separate
`compass.query-review-candidates/1` queue; neither format is a judgment corpus.

Structural `init`, `update`, `extract`, and `watch` builds publish
`program.json` only when `--program` or `--program-artifact` is selected. The
legacy `--no-program` flag remains accepted and continues to request the
Expand Down
49 changes: 49 additions & 0 deletions PERFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,55 @@ Compare a proposed change with a previously approved Compass result captured on
the same runner and corpus. A median regression above 10% requires explicit
review and evidence explaining the tradeoff.

## Query-relevance qualification

The native query-relevance gate keeps two intentionally separate evidence
sets: the checked-in 80-question reviewed synthetic corpus validates fixture,
schema, scoring, and metric behavior; a 23-question, production-shaped
executable subset runs actual
`CodeQueryEngine::query_natural` requests for search, callers, callees, impact,
path, and no-answer cases against the support graph. The executable subset
therefore qualifies the planner and typed operation together. It derives its
canonical graph digest, records measured latency and serialized response bytes,
and requires matching ordered observations from JSON, store, and a repeated
store execution. Timing is measured but removed before the deterministic
response-baseline comparison.

Run the gate with this checkout's external Cargo target:

```bash
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
python3 scripts/qualify_query_relevance.py
```

The gate fails on corpus/schema/digest drift, non-deterministic backend output,
or a reviewed minimum metric miss. Its thresholds currently require perfect
Success@1, edge-direction precision, path acceptance, and no-answer precision
for the deliberately small executable graph. It reports MRR, Recall@k, nDCG,
intent macro-F1, edge-kind/direction precision and recall, backend parity,
latency percentiles, and observable response-byte work. Candidate, posting,
and expansion counters are not public query-engine observations and remain
explicitly uninstrumented rather than inferred from output sizes.

Refresh a judged corpus, executable request, digest expectation, or threshold
only with a reviewed intent/identity change and updated deterministic evidence;
never regenerate expected judgments or thresholds from a proposed ranker.

The typed search path has hard-cut to `query-ranker/2`; no environment switch
can restore v1. The gate includes a reviewed production-versus-generated
exact-name ambiguity for which frozen test-only v1 loses at rank one and v2
wins, while all executable questions retain perfect Success@1. To expand the
baseline with real production vocabulary, run
`scripts/prepare_query_relevance_review.py` on an approved local JSONL export,
then follow the two-reviewer, graph-digest-pinned process in the relevance
fixture README. Importer output is a review queue, never a generated truth set.

Search work is bounded independently from response size: `maxCandidates`
limits the total multi-source recall pool and is never expanded to
`maxNodes`. The default ranks at most 20 recalled candidates. The existing
100,000-node in-process ceiling now covers direct search and natural-query
planning as well as callers, impact, and node trails.

## Compass Store release qualification

The local store release harness records the adapter's build/query timings,
Expand Down
16 changes: 11 additions & 5 deletions crates/compass-cli/assets/compass-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ codebase question:
1. Run `compass reflect --if-stale`.
2. Read `compass-out/reflections/LESSONS.md` if it exists and is relevant.
3. Run `compass query "<question>"` before broad source searches. Keep the
2,000-token default for a focused question, or set `--budget N` based on the
context available for graph evidence.
automatic typed result for a clear search, callers, callees, impact, or path
intent. For broader relevance traversal, pass `--traverse`; keep its
2,000-token default or set `--budget N` based on the context available for
graph evidence.
4. Read the final `Pagination:` line when present. If it reports `next=N`,
repeat the same query, graph/revision selector, contexts, traversal mode, and
budget with `--page N`. Follow pages through `next=none` before making an
Expand All @@ -82,6 +84,8 @@ codebase question:

Use the specialized navigation commands when they fit:

- `compass ask "<question>"` to require bounded, typed intent routing directly;
inspect the reported operation and ambiguity.
- `compass search "<symbol>"` for exact or fuzzy typed-symbol lookup.
- `compass callers` or `compass callees` for one-hop call-graph evidence.
- `compass call-graph` for a bounded caller/callee trace from a source position
Expand Down Expand Up @@ -117,9 +121,9 @@ debug a graph result; it should not silently replace the graph-first workflow.

Classify the effect before selecting a command:

- Read-only local: `search`, `callers`, `callees`, `impact`, `explore`, `node`,
`call-graph`, `query`, `program`, `path`, `explain`, `affected`, `tree`, and
local diagnostics.
- Read-only local: `ask`, `search`, `callers`, `callees`, `impact`, `explore`,
`node`, `call-graph`, `query`, `program`, `path`, `explain`, `affected`,
`tree`, and local diagnostics.
- Local publication: `init`, `update`, `extract`, `watch`, `cluster-only`,
`label`, history materialization, installation, and file-based exports.
- External or credentialed: semantic providers, URL ingestion, cloning, PR
Expand Down Expand Up @@ -171,6 +175,8 @@ Do not force every request through `query`:
- Dependency route: `path`.
- Change-review scope: `affected`.
- Exact relationship or automation: `query --cql`.
- Direct natural-language structural question: `ask`; inspect the typed
operation before using its evidence.
- Exact symbol or call evidence: `search`, `callers`, `callees`, `call-graph`,
`explore`, `node`, or `program`.
- Repository structure: `tree`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ whether a Compass capability is covered by the installed skill. Run

- `compass capabilities`: report versioned, read-only machine contracts for
editor and automation integrations.
- `compass ask`: route a direct natural-language structural question to a
bounded, deterministic typed query operation.
- `compass search`: find typed symbols by name using the local FTS index.
- `compass callers`: list direct typed call-graph predecessors.
- `compass callees`: list direct typed call-graph successors.
Expand Down
15 changes: 15 additions & 0 deletions crates/compass-cli/assets/compass-skill/references/query.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@ Load this reference for codebase questions when a graph exists.

```bash
compass query "where is authentication enforced?"
compass query "who calls PaymentGateway.charge?"
compass query "path from CheckoutController.create to PaymentGateway.charge"
compass query "payment retries" --traverse
compass query "payment retries" --dfs
compass query "payment retries" --budget 1500
compass query "payment retries" --budget 8000
compass query "payment retries" --budget 8000 --page 2
compass query "payment retries" --context CheckoutService
```

Clear search, callers, callees, impact, and path questions against a current
typed graph use the bounded typed query framework automatically. Generic or
contradictory questions retain broad relevance traversal. Use `--traverse` to
select traversal explicitly; `--dfs`, `--context`, `--budget`, and `--page` do
so as well. Historical `--at` queries always use traversal.

The default traversal favors broad relevant context. Use `--dfs` when tracing a
specific chain. A token budget bounds rendered output; it does not change graph
contents. Keep the 2,000-token default for a focused question. Raise it for a
Expand Down Expand Up @@ -43,6 +52,8 @@ compass query "authentication flow" --at HEAD~20
## Focused graph operations

```bash
compass ask "who calls PaymentGateway.charge?"
compass ask "what depends on authorizePayment?"
compass search PaymentGateway
compass callers PaymentGateway.charge
compass callees CheckoutController.create
Expand All @@ -56,6 +67,10 @@ compass affected authorizePayment --depth 3
compass tree
```

- `ask` requires deterministic routing of a direct natural-language question
to a bounded typed operation such as search, callers, callees, impact, or
node trail. Treat the reported operation and any ambiguity as part of the
result.
- `search` resolves typed symbols by exact or fuzzy name.
- `callers` and `callees` walk one attributable call-graph hop.
- `impact` traverses a bounded transitive radius and excludes heuristic
Expand Down
7 changes: 6 additions & 1 deletion crates/compass-cli/src/code_query_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use compass_model::query_contract::{
CallRequest, CodeQueryLimits, CodeQueryResponse, ExploreRequest, ImpactRequest,
NodeTrailRequest, SearchRequest,
};
use compass_query::{EngineSelection, open_with_engine};
use compass_query::{EngineSelection, NaturalQueryRequest, open_with_engine};

use crate::Outcome;

Expand Down Expand Up @@ -66,6 +66,11 @@ fn execute(operation: &str, args: &[String]) -> Result<CodeQueryResponse, String
.map_err(|error| error.to_string())?;
let limits = limits(args)?;
match operation {
"ask" => engine.query_natural(NaturalQueryRequest {
question: required(&positional, 0, "ask <QUESTION>")?.to_owned(),
include_heuristic: args.iter().any(|arg| arg == "--include-heuristic"),
limits,
}),
"search" => engine.search(SearchRequest {
query: required(&positional, 0, "search <QUERY>")?.to_owned(),
limits,
Expand Down
11 changes: 9 additions & 2 deletions crates/compass-cli/src/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const GROUPS: &[Group] = &[
Group {
title: "Explore",
commands: &[
"ask",
"search",
"callers",
"callees",
Expand Down Expand Up @@ -142,6 +143,12 @@ const GROUPS: &[Group] = &[
];

const PAGES: &[Page] = &[
page!(
"ask",
"Route a natural-language question to a typed code-graph query",
["compass ask <QUESTION> [OPTIONS]"],
"Arguments:\n <QUESTION> Natural-language code-graph question\n\nOptions:\n --graph <PATH> Typed graph [default: compass-out/graph.json]\n --program <PATH> Optional Program IR enrichment\n --cache <DIR> Query-index cache directory\n --engine <default|json|store> Graph storage engine [default: default]\n --max-depth <N> Traversal radius\n --max-nodes <N> Node bound\n --max-edges <N> Edge bound\n --max-paths <N> Path bound\n --max-candidates <N> Candidate bound\n --include-heuristic Include heuristic evidence\n --format <text|json> Output format [default: text]\n\nExamples:\n compass ask \"who calls PaymentService.charge?\"\n compass ask \"what does CheckoutController.create call?\" --format json\n compass ask \"path from CheckoutController.create to PaymentGateway.charge\"\n\nNotes:\n High-confidence callers, callees, impact, and path questions route to the matching typed operation. Contradictory or low-confidence input falls back to bounded symbol search. The response uses compass.query/1."
),
page!(
"call-graph",
"Trace callers and callees for a source position or symbol",
Expand Down Expand Up @@ -274,7 +281,7 @@ const PAGES: &[Page] = &[
"compass query --cql --stdin",
"compass query --cql --repl"
],
"Arguments:\n <QUESTION> Natural-language graph question\n <QUERY> Inline CompassQL query\n\nOptions:\n --dfs Use depth-first traversal\n --context <VALUE> Add query context\n --budget <N> Approximate tokens per natural-query page [default: 2000]\n --page <N> Natural-query result page, starting at 1 [default: 1]\n --graph <PATH> Read a graph JSON file\n --at <REV> Query an immutable Git revision; conflicts with --graph\n --cql Use CompassQL mode\n --file <PATH> Read CompassQL from a file\n --stdin Read CompassQL from standard input\n --repl Start the interactive CompassQL shell\n --param <NAME=VALUE> Bind a parameter; repeatable\n --params-file <PATH> Read parameters from JSON\n --format <table|json|jsonl> Result format [default: table]\n --output <PATH> Write results to a file\n --timeout-ms <N> Execution timeout [default: 5000]\n --max-rows <N> Row limit [default: 10000]\n --max-path-depth <N> Path-depth limit [default: 32]\n --max-expanded-relationships <N> Relationship expansion limit [default: 5000000]\n --max-memory-bytes <N> Memory limit [default: 268435456]\n\nExamples:\n compass query \"authentication flow\"\n compass query \"payment service\" --budget 8000\n compass query \"payment service\" --page 2\n compass query --cql \"MATCH (n) RETURN n LIMIT 10\" --format json\n compass query --cql --file report.cql --params-file params.json\n\nTips:\n Pagination metadata reports the next page; repeat the same natural query with that `--page`.\n Use `compass path` when you know both endpoints of the relationship to trace."
"Arguments:\n <QUESTION> Natural-language graph question\n <QUERY> Inline CompassQL query\n\nOptions:\n --traverse Force legacy relevance traversal instead of intent routing\n --dfs Use depth-first traversal and disable intent routing\n --context <VALUE> Add query context and disable intent routing\n --budget <N> Approximate tokens per traversal page [default: 2000]\n --page <N> Traversal result page, starting at 1 [default: 1]\n --graph <PATH> Read a graph JSON file\n --at <REV> Query an immutable Git revision; conflicts with --graph\n --cql Use CompassQL mode\n --file <PATH> Read CompassQL from a file\n --stdin Read CompassQL from standard input\n --repl Start the interactive CompassQL shell\n --param <NAME=VALUE> Bind a parameter; repeatable\n --params-file <PATH> Read parameters from JSON\n --format <table|json|jsonl> CompassQL result format [default: table]\n --output <PATH> Write CompassQL results to a file\n --timeout-ms <N> CompassQL execution timeout [default: 5000]\n --max-rows <N> CompassQL row limit [default: 10000]\n --max-path-depth <N> CompassQL path-depth limit [default: 32]\n --max-expanded-relationships <N> CompassQL relationship expansion limit [default: 5000000]\n --max-memory-bytes <N> CompassQL memory limit [default: 268435456]\n\nExamples:\n compass query \"who calls PaymentService.charge?\"\n compass query \"path from CheckoutController.create to PaymentGateway.charge\"\n compass query \"authentication flow\"\n compass query \"authentication flow\" --budget 8000 --page 2\n compass query \"who calls PaymentService.charge?\" --traverse\n compass query --cql \"MATCH (n) RETURN n LIMIT 10\" --format json\n compass query --cql --file report.cql --params-file params.json\n\nTips:\n High-confidence search, callers, callees, impact, and path questions use the bounded typed query framework. Generic, contradictory, historical, or explicitly traversed questions retain paginated relevance traversal.\n Pagination metadata reports the next traversal page; repeat the same query with that `--page`."
),
page!(
"program",
Expand Down Expand Up @@ -1099,7 +1106,7 @@ mod tests {
#[test]
fn catalog_has_unique_complete_public_roots() {
let roots = root_commands();
assert_eq!(roots.len(), 46);
assert_eq!(roots.len(), 47);
for root in roots {
let matches = PAGES.iter().filter(|page| page.path == root).count();
assert_eq!(matches, 1, "{root}");
Expand Down
Loading
Loading