usm/query-layer [built]
Predicate query language over .usm data — a tiny expression grammar (selectors, comparisons, and/or/not, has, contains) evaluated against parsed .usm files, exposed as usm query CLI and usm_query MCP tool. Turns grep-and-guess into typed impact analysis.
Status: built
Intent
Agents currently list everything or grep raw YAML to answer questions like "which planned features have no contracts?" or "what does this service own?". The semantic model is where computation should live (Fowler): a typed query surface over parsed .usm data serves drift checks, impact analysis, and triage — for agents via MCP and humans via CLI. Read-only; touches nothing about storage or format.
Decisions
tiny-grammar-not-sql
Decision: A ~200-line recursive-descent grammar, not SQL/jq subset
Rationale: Covers selector+predicate use cases agents actually have; keeps error messages precise and the surface teachable in one rules-file line.
missing-field-is-false
Decision: Unknown/absent fields make predicates false instead of erroring
Rationale: Queries like 'feedback where severity = high' must not explode on feature files that lack severity; absence is simply not a match.
Flows
Run a query from the CLI (run-query-cli)
- parse → query string into selector + predicate AST
- collect → all .usm files in the monorepo (same discovery as validate/generate)
- evaluate → filter files by selector and predicate
- output → table lines by default, --json for full objects, --limit cap
Run a query via the usm_query MCP tool (query-via-mcp)
- accept → query string + optional limit
- evaluate → same parser and evaluator as CLI
- return → id/type/status/summary/path per hit, total count, truncated flag (capped at 50 default)
Compose predicates (compose-predicates)
- support → selectors: features services systems apis data policies operations feedback all
- support → comparisons: = != > < >= <= ~ (contains) and has <field>
- support → boolean: and or not with parentheses; fields: type id status summary intent system service kind severity contracts flows tests decisions interfaces version
Contracts
selector-and-predicates
The grammar covers type selection, field comparison, existence, contains, and boolean composition
Acceptance criteria:
- [ ] Selector maps to $type filtering (features→feature etc, all→any)
- [ ] = != on strings; > < >= <= on numeric fields (array lengths, version)
- [ ] ~ substring contains case-insensitive; has field for existence/non-empty
- [ ] and or not with parentheses, standard precedence (not > and > or)
friendly-errors
Parse failures produce actionable messages, never raw stack traces
Acceptance criteria:
- [ ] Message names the token and position and what was expected
- [ ] Unknown fields resolve to missing (has is false, comparisons false) rather than erroring
read-only-and-capped
Query never writes; MCP results are capped for context safety
Acceptance criteria:
- [ ] No file writes on any query path
- [ ] MCP default limit 50 with total + truncated in the response
one-evaluator-two-surfaces
CLI and MCP share a single parser/evaluator module
Acceptance criteria:
- [ ] src/query module is the only implementation
- [ ] MCP response includes path so agents can usm_read hits directly
Tests
parser-cases
Given:
- query_strings: ["features where status = planned","features where contracts > 0 and not (status = deprecated)","all where summary ~ auth","services where has decisions"]
Then:
- assertion: each parses to expected AST without error
- assertion: malformed string yields friendly parse error with position
evaluator-cases
Given:
- fixture_usm_files: "feature planned w/o contracts, feature built w/ 2 contracts, service, feedback high"
Then:
- assertion: status = planned returns only the planned feature
- assertion: contracts > 0 returns the built feature
- assertion: all where summary ~ AUTH matches case-insensitively
- assertion: feedback where severity = high returns the feedback file
cli-smoke
Given:
- fixture_project: true
Then:
- assertion: usm query 'features where status = planned' prints matching ids
- assertion: --json emits parseable JSON array
mcp-tool
Given:
- fixture_project: true
Then:
- assertion: usm_query returns results with id and path
- assertion: limit caps results and sets truncated true
Implementation
- Primary: src/query/index.ts
- Test code: tests/query.test.ts
- Test code status: manual
See Also
- usm/mcp-read
- usm/cli-generate