Spec Search Queries
SpecForge is intended to be a tool for organizing specifications. To this end, specs can be annotated with docstrings, labels, aliases and custom fields. Specforge systems can be queried for relevant specs using the CLI or the sidebar in the VSCode Extension.
Syntax and Semantics of Queries
The spec search utilizes a query language similar to the GitHub Search Syntax or LIQE.
It supports fuzzy or exact search based on the docstrings and definition names, comparison of numerical fields, filtering by labels, and boolean combinations of multiple filters. Specs can also be sorted using numerical fields.
Atomic Constructs
Fuzzy and Exact Text Search
To search specs using text, directly type your query. E.g., use pump to search for specs which mention pump in their name, aliases or their docstring.
By default, text search is fuzzy. Use quotes (e.g., "pump") to enforce an exact search.
When there are multiple fuzzy or exact terms (separated by space), we interpret the query as a disjunction of these queries. For example, the query tube "pump" will match specs matching tube fuzzily or "pump" exactly.
Predicates on Fields
Queries can specify filters based on the values of custom fields.
- Comparison: Assuming the existence of a field named
priority, one can write queries likepriority:>50,priority:>=50, etc. - Booleans: Given a Boolean field
reviewed, one can writereviewed:trueorreviewed:false. - Strings: One can compare a string field
reviewer, one can writereviewer:Samorreviewer:"Samwell Tarly". - Constructors: A predicate can be used to match against a constructor. To do so, prefix the constructor with
#as usual. E.g.,color:#Red.
Labels
Queries can filter using labels. E.g., label:todo will match all the items with the todo label.
Systems
Queries can also filter specs based on the system they belong to. For example, system:engine will match specs only in the engine system. This can also be a qualified name, such as system:cooling::pump.
Depends-On
The depends-on: construct can be used to filter specs based on other specs, defs, signals or params that are used to define them. For example, depends-on:pressure will match spces that depend on the pressure signal (or possibly a def or param named pressure). This can also be a qualified name, such as depends-on:chamber2::pressure.
Boolean Combinations
The query language also supports boolean combinations of multiple queries using AND, OR, and NOT. Parentheses can be used to group queries.
The NOT operator can also be written using a - prefix. For example, -label:todo is equivalent to NOT label:todo.
When explicit connectives are not used, we interpret the query as follows. When a group of atomic constructs are seperated by space, the fuzzy and exact textual search terms are combined using disjunction and the predicates are combined using conjunction. E.g., tube "pump" priority:>50 label:todo is interpreted as (tube) OR ("pump") AND (priority > 50) AND (label:todo). To consider another example, (NOT priority:>10) reviewed:true label:important foo bar is interpreted as (NOT priority > 10) AND reviewed:true AND label:important AND (foo OR bar).
Sorting
To sort the results of a query, use the sort: keyword followed by the field name. For example, adding sort:priority to the end of a query will sort the results in descending order of the priority field.
To sort in ascending order, append -asc to the field name. For example, sort:priority-asc will sort the results in ascending order of the priority field. Similarly, add -desc to sort in descending order. By default, the sorting is in descending order.
Multiple sort queries can be used to specify tie-breaking rules. For example, sort:priority sort:created_at will sort the results by priority in descending order, and break ties using created_at in descending order.
Sorts can be combined with filtering queries by seperating them with a space. For example, label:todo sort:priority will filter the specs with the todo label and sort them by the priority field.
Validation
It is sometimes desirable to check that the results of a query satisfies a logical coherence condition. For instance, one might want to check that all specs with the label todo have a priority field greater than 50.
You can use the validate CLI command to check that the results of the antecedent query are contained in the results of the consequent query. For the above example, you can run the following command in the terminal:
specforge validate --antecedent 'label:todo' --consequent 'priority:>50'
Alternatively, you can specify the validation rules in specforge.toml (see Project Configuration) as follows:
[[validation_rules]]
antecedent = "label:todo"
consequent = "priority:>50"
[[validation_rules]]
antecedent = "label:blue OR label:green"
consequent = "label:grue"
Running specforge validate without any arguments will check all the validation rules specified in specforge.toml. The VSCode extension will also automatically show warnings for validation rules in the specforge.toml file that are not satisfied.
Bulk Labeling
The bulk-label CLI command can be used to add a label to all specs matching a query. For example, the following command will add the important label to all specs with priority greater than 50:
specforge bulk-label --query 'priority:>50' --label 'important'
Similarly, the following command will add the label grue to all specs that satisfy label:green or label:blue:
specforge bulk-label --query 'label:green OR label:blue' --label 'grue'