Conversation
Phase 1 of the V3 query plan: ports the 9-table APM schema from the appmap-apm prototype and adds openQueryDb / queryDbPath helpers with WAL, foreign keys, and user_version stamping. No CLI wiring yet — schema and lifecycle only, with unit tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Slice 2 of the query DB work. Ports the AppMap → SQLite importer from the
appmap-apm Python prototype, wires it into FingerprintQueue/Watch/Directory
commands, and adds a cross-validation script that diffs the TS importer's
output against the Python prototype's on a shared fixture set.
- Per-concern importer modules under cmds/query/db/import/: parseLocation,
parentEventMap, returnEventMap, codeObjects, appmapRecord, httpRequests,
httpClientRequests, sqlQueries, functionCalls, exceptions, importAppmap.
- QueryDbIndexer subscribes to FingerprintQueue's index event for adds/
changes and to FingerprintWatchCommand's removed for unlinks; also runs
syncDirectory to bootstrap when query.db is fresh but fingerprints exist.
- fqid construction mirrors @appland/models' codeObjectId.js (slash
between packages, :: between nested classes, . / # for functions).
- Exceptions carried on return events use the call event id for event_id
and parent_event_id, fixing the silent-NULL bug surfaced by the spec.
- Type-only imports from @appland/models for HttpServerRequest/Response,
HttpClientRequest/Response, SqlQuery, ExceptionObject, CodeObjectType,
Label. Built JS contains no runtime require('@appland/models').
- Drop the findings table from schema.ts; out of scope for this port.
- scripts/validate-against-python.ts: runs both importers on a fixture set
and diffs row counts + key fields per table. Currently passes with all
rows matching across appmaps, code_objects, http_requests, sql_queries,
function_calls, and exceptions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a `query` subcommand that reads the query DB built during fingerprinting and exposes endpoints, find, and tree verbs, with shared formatting/filter helpers and unit tests. Extends the Python validation script to compare the TS query layer against `server.services.queries.get_endpoints` on the same DB. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the one-off Python parity script; not needed going forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…emo script
The query-DB path was previously selectable by either an APPMAP_QUERY_DB
env var (carried over from the Python prototype's APM_DB_PATH) or a --db
flag on the query verbs. Both forms had problems:
- The env var didn't fit the rest of the CLI's idiom (flags + appmap.yml,
not env-driven configuration), and was dead in the verb path because
locateAppMapDir ran before the env-var lookup.
- --db was ambiguous in a CLI that may grow other databases (thread
history, snippet index, etc.); query-db scopes the name.
Drop the env var; rename --db to --query-db across appmap index and the
three query verbs; route the flag through openQueryDb / openReadOnly.
queryDbPath is now a pure SHA-derivation function; explicit overrides go
through the flag, not the environment.
Also: scripts/demo-query.sh — a small bash demo that builds a query.db
from a fixture set (defaults to appmap-apm/tests/fixtures if present, else
the bundled ruby fixtures) and exercises endpoints, find queries, find
exceptions, tree --format=summary, and tree --filter=sql against it. Useful
for attaching to PR descriptions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three changes batched together because they share schema bumps and the
class/method filter touches both code paths.
- hotspots verb: function-mode (CALLS / TOTAL_MS / SELF_MS via a
one-pass child-time CTE) and sql-mode (COUNT / AVG / TOTAL grouped
by sql_text). New verbs/hotspots.ts and queries/hotspots.ts.
- lib/scope.ts: extracted recording-scope helpers (parseRoute,
appmapWhere, httpScopeClauses, appmapIdScope) that find and
hotspots both use. find.ts thinned by ~80 lines.
- Schema v2 → v4:
v2: drop http_requests.timestamp (denormalized copy of
appmaps.timestamp; nothing read it after endpoints switched
to filtering on a.timestamp).
v3: replace code_objects.defined_class + method_id with
package, class, method, is_static — components are stored
separately so filters can match by exact equality without
parsing the fqid string.
v4: replace `class` (::-joined string) with `classes` (JSON
array) + denormalized `leaf_class`. Eliminates the implicit
delimiter convention and the LIKE '%::' || ? suffix matches
for short-form filters.
- --class and --method (find calls / hotspots) now use the normalized
columns: leaf_class for short forms, classes for explicit chains,
package as a stricter qualifier when supplied. parseClassRef
(also exported) parses V3-canonical and short forms, including
Ruby/C++ Cls1::Cls2 chains and Java/Python dot-form opaque names.
Falls back to the raw function_calls.defined_class for rows
without a code_object link.
- Endpoints fixes: --since/--until filter on a.timestamp (consistent
with find); --sort sorts nulls last; --status describe documents
its HAVING-style semantics.
- --query-db replaces --db on appmap index and the query verbs;
APPMAP_QUERY_DB env var is gone.
- scripts/demo-query.sh exercises endpoints, find, tree, hotspots.
Tests: 132 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`find <type>` previously accepted every filter flag silently and just
ignored the ones that didn't apply to the chosen type, which is a
foot-gun (--class against find appmaps returned all appmaps as if no
filter were given).
Validation rules:
- Universal flags work everywhere: --branch, --commit, --since,
--until, --appmap (recording-scope) plus --limit, --offset, --json
(output).
- Per-type filter flags are accepted only on types where they make
sense; using one elsewhere errors with a clear message:
find appmaps: rejects class, method, label, duration, table,
exception
find requests: rejects class, method, label, table, exception
find queries: rejects label, exception
find calls: rejects table, exception
find exceptions: rejects class, method, label, duration, table
Eight tests in tests/unit/cmds/query/verbs/find.spec.ts pin each rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tput
ExceptionNode was built without path/lineno even though the importer
stores them and findExceptions exposes them. The tree view of an
exception was strictly less informative than \`find exceptions\` —
just the class and message, no source location.
- ExceptionNode now carries path/lineno; tree() reads them from the
exceptions table.
- TreeSummary.exceptions exposes the same fields.
- renderTree / renderFlat / renderSummary append " @ <path>:<lineno>"
to the EXC line when a path is present, matching what find
exceptions shows.
Test pinned in tree.spec.ts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI surfaced a TS2345 against query.ts:
Argument of type 'typeof import("…/verbs/endpoints")' is not
assignable to parameter of type 'CommandModule<{}, any>'.
The verbs declared their builder as `(args: yargs.Argv) => …` (no
generic), which doesn't match `CommandModule<T, U>.builder?: (args:
Argv<T>) => Argv<U>`. The existing rpc command works because its
builder is generic: `<T>(args: yargs.Argv<T>) => …`. Match that
pattern across all four query verbs and the parent query command.
No runtime behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…g, hints
Six small but visible fixes from review:
1. findAppmaps's route-filtered branch was non-deterministic — GROUP
BY a.id with non-aggregated h.* lets SQLite pick any row. Replaced
with a correlated subquery that picks the http_request with the
smallest event_id matching --route / --status. Tested against a
recording with two POST /orders entries (event_id=1 elapsed=100,
event_id=2 elapsed=999); the row consistently shows 100.
2. find appmaps --duration was silently rejected. Now applies on
a.elapsed_ms (the recording-level total).
3. parseRoute matched HTTP methods case-sensitively. Now matches
case-insensitively and normalizes to upper-case so
`--route "post /orders"` works.
4. Appmap-ref matching (find / hotspots / tree) used
`source_path LIKE '%/<ref>.appmap.json'` — broken on Windows
separators and on stores that don't end in .appmap.json. Replaced
with a GLOB clause that handles either separator and matches with
or without the .appmap.json suffix; factored as appmapRefClause()
so all three call sites use it.
5. find requests rejects --method (correct — there's no function
method on a server request) but the error didn't help users find
the right flag. Added a hint:
find requests: --method is not supported for this type
--method: to filter by HTTP method, use --route "METHOD /path"
6. New tests covering each of the above (case-insensitive method,
deterministic findAppmaps, --duration on appmaps, basename-match
with Unix/Windows/no-extension paths, and the --method hint).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d queries
Two larger pieces plus three smaller fixes batched together.
- endpoints aggregation moves to SQL: a CTE ranks each request within
its (method, route) partition by elapsed_ms NULLS LAST; the outer
GROUP BY computes count, avg_ms, p95_ms (via the rank that hits
ceil(0.95 * measured_count)), and err_pct in a single query, with
HAVING for --status and ORDER BY ... DESC NULLS LAST + LIMIT in SQL.
No more fetching the full row set into JS just to slice it.
- find queries --class / --method now resolve via the parent
function_call's code_object (parent_event_id → function_calls →
code_objects), not just the denormalized caller_class string. New
sqlCallerClassClauses / sqlCallerMethodClauses helpers that mirror
classFilterClauses' code-object-first / fallback-to-raw-string
pattern, scoped to sql_queries via parent_event_id. The fallback
fires when the parent function_call has no code_object link.
rawClassMatchClauses removed (replaced).
- hotspots --type=sql now rejects --class instead of silently
dropping it. Function-mode is the only place --class applies.
- tree --format=summary now rejects a non-default --filter — the
summary aggregates over all event types so combining with --filter
is ambiguous.
- findQueries seed in tests now supports parent_event_id, used by
the new test that pins code-object matching even when caller_class
is wrong.
- Stale comment in endpoints.ts referencing the dropped
http_requests.timestamp column updated.
Tests: 159 passing (+8 new for class/duration/since/commit coverage,
parent-link findQueries match, etc.).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s flag validation
- Importer: code_objects lookup keyed by "<location>|<method>" rather
than just "<location>", so multiple functions sharing a path:lineno
(e.g. Spring Data proxy methods) bind to their own code_objects
instead of clobbering one another. Verified against PetClinic
fixtures: findById and findPetTypes now resolve to distinct
code_object_ids; previously both linked to the same one.
- find verb: added buildFindFilter() that parses --class via
parseClassRef and routes the parsed method through filter.method.
Makes the documented "Class#method" form's behavior explicit at
the verb layer rather than depending on internal helpers each
parsing it again. Explicit --method wins over a method embedded
in --class. Exported for tests.
- hotspots verb: replaced the inline `if (sql && class) throw` with
a REJECTED_FLAGS table mirroring find's. Same shape, easy to
extend when future filters land.
- Coverage: tests for hotspots --since/--until and tree --filter
paths (previously unexercised), plus a test pinning the importer
fix (two functions at the same path:lineno disambiguated by name).
- --route describe text now calls out "path is exact match; method
case-insensitive" on both find and hotspots.
Tests: 171 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…gnability Each verb's handler was typed `(argv: ArgumentsCamelCase<Argv>) => …`, which is more specific than what `args.command(VerbModule)` infers when the verb is imported as `import * as VerbModule`. yargs widens U to `any` at that boundary, and a strict-typed handler isn't assignable to the widened form. CI surfaced this as TS2345. Match the pattern landed earlier on rpc.ts and confirmed for the query verbs in 5a661bd9: accept `ArgumentsCamelCase<unknown>` at the export and immediately downcast to the precise `ArgumentsCamelCase<Argv>` inside the handler. No runtime change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@typescript-eslint/array-type flagged ten Array<T> usages across queries/endpoints.ts, queries/tree.ts, verbs/find.ts and three test files. Mechanical rewrite — no behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the V3 query verb set: related (similarity ranking) and compare
(per-route latency delta between branches). Both ride on the existing
shared helpers — appmapWhere/httpScopeClauses for filtering, endpoints()
for compare's p95 — so the semantics line up across verbs.
- related <appmap>:
Loads the source recording's signature (route, SQL tables,
classes), then for each candidate appmap (filters: --branch,
--commit, --since/--until, --status, --route, --limit) computes a
score and a list of contributing signals. Score weights from V3:
route ×5 (binary), per-shared-table ×3, per-shared-class ×2.
Source is excluded; results are ranked by score descending.
SQL-table extraction from sql_text is a regex over
FROM/JOIN/INTO/UPDATE — heuristic (won't handle nested
subqueries cleanly), but the score is itself a heuristic so the
precision floor is acceptable.
Class-set merges code_objects.leaf_class (linked rows) with a
leaf-extracted defined_class for unlinked rows so sparsely-linked
recordings still contribute to the score.
- compare <branch-a> <branch-b>:
Calls endpoints() twice, one per branch, then merges results by
(method, route). Reuses the same SQL window-function p95 that
endpoints does, so the two verbs agree per-route. delta = b_p95
/ a_p95; the verb formats it as "+Nx" / "-Nx" / "+N%" / "~" /
"?". --sort=delta|p95-a|p95-b, --include-counts, --since/--until,
--limit, --json.
- demo-query.sh exercises related against the PetClinic /oups
recordings; compare is silent on PetClinic (single branch) but the
verb is wired and tested.
Tests: 181 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`tree` previously dumped every event for the recording — fine on a 10-event test fixture, useless on a real production trace with thousands of events. V3 lists --focus-fn / --focus-sql / --ancestors / --descendants for exactly this; we'd just deferred them. Adds focus options to the tree() query function: --focus-fn <fqid> function calls matching code_object.fqid --focus-sql <pattern> sql_queries whose text contains <pattern> --focus-route <path> server requests matching normalized_path --focus-url <pattern> outbound HTTP whose URL contains <pattern> --ancestors N ancestor levels above each match (default 5) --descendants N descendant levels below each match (default 3) --min-elapsed-ms N prune subtrees with max elapsed below N Multiple focus flags allowed; their match sets are unioned. The filtered subset includes: focus events + N ancestors + the direct children of every ancestor (so siblings of the focus are visible) + M descendants of focus. Depth is recomputed relative to the highest included ancestor so indentation reads cleanly. --min-elapsed-ms walks subtrees post-order and drops any whose entire branch's max elapsed is below the threshold — useful for trimming traces dominated by fast leaf calls. Tests cover each focus type, depth budget edges (ancestors=1, descendants=0), multi-focus union, min-elapsed pruning, no-match returning empty, and the relative-depth reanchoring. 190 total passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`appmap query mcp` runs an MCP (Model Context Protocol) server on
stdio. Tool names match the Python prototype's MCP surface so existing
clients work unchanged; under the hood each tool is a thin wrapper
around the V3 query functions we already have.
Tools shipped (9):
get_endpoint_detail → find requests filtered by method+path
get_slow_queries → find queries, sorted by elapsed desc
get_function_hotspots → hotspots(type=function)
get_exceptions → find exceptions
get_log_events → find calls --label=log
get_labeled_events → find calls --label=<X>
compare_branches → compare(branch_a, branch_b)
get_request_trace → tree() with focus support
get_related → related()
Resource shipped:
appmap://endpoints → endpoints(limit=200)
`get_request_trace` accepts the Python signature: focus_type +
focus_value (function | sql_query | http_server_request |
http_client_request) → maps to the V3 tree focus flags. parent_depth /
child_depth / min_elapsed_ms thread through. Works against either a
numeric appmap_id or a name/basename ref.
Implementation:
- queries/mcp.ts: tool registry + JSON-RPC dispatcher (initialize,
tools/list, tools/call, resources/list, resources/read,
notifications/* are no-op). Hand-rolled — no SDK dependency. ~360
lines.
- verbs/mcp.ts: stdio loop. Reads newline-delimited JSON-RPC from
stdin, writes responses to stdout, logging only to stderr (so the
protocol stream stays clean).
- tests/unit/cmds/query/queries/mcp.spec.ts: 11 cases covering
initialize, tools/list, tools/call (with content envelope),
resources/list, resources/read, unknown method/tool errors,
appmap_id resolution by id and name.
Smoke test against the PetClinic fixture set returns real hotspot
rows; piped JSON-RPC roundtrip verified end-to-end.
Total tests: 201 passing.
Deferred (have V3-CLI workarounds; can add as separate tools later):
- search (free-text + structured)
- get_dashboard, get_code_context, get_class_context, get_labels
Rejected (no findings table in our schema):
- get_findings, get_findings_summary
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the Python-prototype tool names — we don't need to match them and
the new surface reads better for LLM consumption. Each tool name now
uniquely identifies what gets returned, with consistent "find_*" /
"list_*" / "get_*" prefixes where the verb adds clarity and bare
nouns where the type itself is the answer.
Renames / new (11 tools, was 9):
list_endpoints (new) per-route summary
function_hotspots was get_function_hotspots
sql_hotspots (new) sql_hotspots ranking
find_recordings (new) appmap rows
find_requests (replaces get_endpoint_detail; generic filter)
find_queries (replaces get_slow_queries; sort via duration)
find_calls (replaces get_log_events / get_labeled_events;
filter by --label=log or =security.* etc.)
find_exceptions was get_exceptions
get_call_tree was get_request_trace
find_related was get_related
compare_branches unchanged
Also: appmap arg renamed from "appmap_id" to "appmap" (it accepts both
numeric id and name; the previous name implied id-only).
The old Python-named tools are gone — clients will need to update.
Internally each tool is still a thin wrapper around the V3 query
functions; the renames are purely cosmetic.
Tests updated; 202 passing. tools/list verified end-to-end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ngs' - Each MCP tool description now lists its return columns inline; function_hotspots and get_call_tree include fqid format examples. - find_recordings rows expose appmap_id alongside appmap_name; get_call_tree accepts either. - `appmap query find recordings` is now an alias for `find appmaps` (matches the MCP find_recordings name and stops `REJECTED_FLAGS[type] is not iterable`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- queries/mcp.ts: collapse interface-with-call-signature into a type
alias (prefer-function-type) and drop a now-redundant cast.
- queries/tree.ts: ancestor walk uses an optional chain (preferred by
prefer-optional-chain), with `== null` so a parent_event_id of 0
still walks up rather than terminating.
- verbs/compare.ts, verbs/mcp.ts, verbs/tree.ts: drop type assertions
that the inferred argv type already provides; the verb-level cast in
handler() (argvIn → ArgumentsCamelCase<Argv>) makes per-flag casts
redundant. (no-unnecessary-type-assertion)
- tests/unit/.../mcp.spec.ts: rewrite two Array<T> casts as T[].
Mechanical lint cleanup; behavior unchanged. tsc + 202 query tests
green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`yarn typecheck` runs tsc --noEmit; `yarn verify` chains lint + typecheck for a single ~12s pre-commit gate. Catches both the lint failures and the CommandModule TS2345 class of issues that have been landing in CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Recommends `yarn verify` from the modified package's directory after substantial change batches; calls out the ~3x speed difference between scoped and full-monorepo verification (~10s vs ~30s). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… tool - function_calls already stored path/lineno; FindCallRow, FunctionHotspotRow, and FunctionNode now project them through the SQL/MCP layer so callers can Read source directly without a follow-up grep. - New list_labels MCP tool surfaces labels with code-object counts and a sample fqid — supports the appmap-fix skill's "what's already labeled" step. - Tool descriptions for find_calls and get_call_tree now state that parameters_json/return_value are populated only for labeled functions. - find verb's calls table gains a LOCATION column. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
scripts/verify.mjs reads `git status` (or `git diff --cached` with
--staged), groups changed files by `packages/<name>/`, and per package
runs ESLint --quiet on only the changed lintable files plus
`tsc --noEmit` on the whole package. Skips files outside packages/ and
packages without a `typecheck` script. Uses the package-local eslint
binary so we pick up its plugin major versions (cli ships ESLint 8 vs
root's 7).
- root scripts: `yarn verify` (working tree) and
`yarn verify:staged` (for hook use).
- CLAUDE.md updated to call out `yarn verify` from repo root after
substantial change batches; ~5–7s scoped vs ~30s full lint.
- No pre-commit hook yet — left for the team to opt into.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surface log calls (functions labeled `log`) as a first-class find type.
Filter by --message (SQL LIKE against parameters_json and return_value),
--logger (class), and the standard appmap-scoped flags. False-positive
matches on parameter names are accepted by design; tighten in
post-processing. Display projection prefers a structured-return
{message, ...} when present, else falls back to a parameter named
message/msg or the first string-typed value.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pass --with-logs N (CLI) or with_logs=N (MCP) to enrich each exception row with the last N log calls preceding it in the same recording, ordered chronologically. The default behavior is unchanged. The exception row also now exposes appmap_id alongside appmap_name so follow-up queries can use either as a join key. Implemented as a per-exception prepared-statement loop scoped by appmap_id and event_id < exception.event_id. Synthetic exceptions with NULL event_id receive an empty recent_logs array. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Function calls whose linked code_object carries the `log` label are now promoted to a dedicated `log` node kind in the tree. Renderers emit them as `LOG Logger.method: <message>` at their event position, with the message extracted via the same projection helper used by find_logs (structured return_value first, then a message/msg-named parameter, then the first string-typed value). The tree CLI verb gains `--filter logs` to flatten the tree to just log lines. The MCP get_call_tree result shape gains the `log` kind in the discriminated union. projectLogMessage moves to lib/logMessage.ts so both the find verb and the tree renderer share one projection rule. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a templated resource that returns every log line from one
recording, ordered by event_id. The {ref} placeholder accepts either
a numeric appmap_id or a recording name/basename — the same forms
find_recordings returns. Templates are listed via the standard
resources/templates/list method; concrete URIs read via
resources/read.
Internally introduces a ResourceTemplateImpl shape and shared
read-response helper so fixed and templated resources share one code
path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two MCP improvements surfaced by end-to-end log testing: - find_exceptions with_logs returned 0 entries when the relevant logs fired *inside* the throwing call. The exceptions table stored only the call-entry event_id, but logs inside the call have event_id > entry. Schema v5 adds return_event_id (the throw point in the event stream) and the with_logs SQL now bounds by it, so logs that fired inside the throwing call are included. The legacy call-event recorder shape leaves return_event_id null and falls back to event_id. - find_logs rows and get_call_tree LogNodes now carry a derived `message` field (using the existing projectLogMessage helper). Callers no longer have to parse parameters_json themselves. Recorder-introduced wrapping quotes (e.g. \"'hello'\") are stripped for display; raw parameters_json and return_value remain on the row. CLAUDE.md gains repo-specific notes about rebuilding the CLI after MCP source changes and the appmap-node cwd gotcha for monorepo TS projects (factored out of the user-agnostic skills). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Search-style filters now match anything reasonable rather than requiring
exact identifiers. The agent's frustration with `find_recordings` not
finding "test_apply_high_id_first_then_low_id" inside a longer basename
was the trigger; this generalizes the fix.
- appmap: substring of name OR source_path. New appmapLikeClause used
by appmapWhere; appmapRefClause stays exact for tree's resolveAppmap.
- label / exception: LIKE %X% (was =).
- route path: LIKE %X% (was exact); method still strict + case-insensitive.
- class / method short forms ("Repo", "create") add a substring fallback
on leaf_class / method / defined_class / method_id. Canonical fqid
inputs (containing `/` or `::`) keep their previous strict matching
so explicit disambiguation isn't broadened. Symmetric change in
sqlCallerClassClauses / sqlCallerMethodClauses.
All list-returning queries now return Page<T> = {rows, total, limit,
offset}:
- Default limit 20 across find_*, hotspots, endpoints, related,
compare. Pass limit=0 for unbounded.
- paginate() helper at lib/page.ts wraps each base query with a
COUNT(*) subquery for the total, then re-runs with LIMIT/OFFSET.
- CLI verbs render rows as before plus a `(showing N–M of TOTAL …)`
footer when truncated. --json emits the full Page object.
- MCP tools return Page directly (text content is JSON.stringify'd
already). Tool descriptions updated: `appmap`/`route`/`class`/
`method`/`label`/`exception` are documented as substring; `limit`
documents the default 20 + 0-for-unbounded.
Tests: 244 passing. yarn verify clean.
Breaking change for any direct caller destructuring the array return —
intentional per user request.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Usage example: