Skip to content

Custom Query DSL & Semantic Linter

symtrace v0.5.0 includes a custom Tree-Sitter Query DSL engine and a dedicated declarative semantic linter (symtrace lint). Developers and security teams can define domain-specific architectural invariants and security checks using standard Tree-Sitter .scm query files placed in .symtrace/queries/.

Declarative AST Semantic Linter (symtrace lint)

Section titled “Declarative AST Semantic Linter (symtrace lint)”

In v0.5.0, you can run semantic lint rules across your entire codebase as a standalone CI step:

Terminal window
# Scan current repository with default rules in .symtrace/queries
symtrace lint .
# Enforce zero warnings in automated CI pipelines (non-zero exit code on violations)
symtrace lint . --max-warnings 0
# Specify custom queries directory
symtrace lint src/ --queries-dir /path/to/my-rules
# Format output as SARIF for GitHub Code Scanning
symtrace lint . --format sarif
FlagDefaultDescription
PATH.Target file or directory to scan
--queries-dir <DIR>.symtrace/queriesDirectory path containing .scm rule files
--max-warnings <N>0Maximum allowed warnings before non-zero CI exit code
--format <FMT>cliLinter output format (cli, json, sarif)

During AST diff analysis or symtrace lint scans, symtrace compiles .scm queries against parsed Concrete Syntax Trees (CSTs). When an AST node matches a query pattern, symtrace extracts severity metadata and surfaces annotated findings.

.symtrace/queries/*.scm
Query DSL Compiler
┌─────────┴─────────┐
▼ ▼
AST Diff Engine symtrace lint (CI)
│ │
▼ ▼
Diff Annotations SARIF / CLI Findings

Rule files are placed under .symtrace/queries/<rule_name>.scm. Each rule can declare optional metadata headers:

  • ;; @severity ERROR | WARN | INFO (default: WARN)
  • ;; @message <custom message template> (supports $file and $line interpolation)
;; .symtrace/queries/no_unwrap.scm
;; @severity ERROR
;; @message Unhandled unwrap() detected in $file:$line: use proper error handling or Result matching
(call_expression
function: (field_expression
field: (field_identifier) @method (#eq? @method "unwrap")
)
) @no_unwrap_violation

1. Flag Security-Sensitive Public API Changes (Rust)

Section titled “1. Flag Security-Sensitive Public API Changes (Rust)”
;; .symtrace/queries/security_api.scm
;; @severity ERROR
;; @message Public security-sensitive API modified in $file:$line
(function_item
visibility_modifier: (visibility_modifier) @vis (#eq? @vis "pub")
name: (identifier) @name (#match? @name "^(auth|crypto|verify|token)")
) @security_api_change

2. Track Modifications to Database Models (Python)

Section titled “2. Track Modifications to Database Models (Python)”
;; .symtrace/queries/orm_models.scm
;; @severity WARN
;; @message Django / SQLAlchemy ORM model altered in $file:$line
(class_definition
superclasses: (argument_list
(identifier) @base (#match? @base "^(Model|BaseModel)$")
)
body: (block) @model_body
) @orm_model_change

3. Flag Exported API Route Changes (TypeScript)

Section titled “3. Flag Exported API Route Changes (TypeScript)”
;; .symtrace/queries/api_routes.scm
;; @severity WARN
;; @message Exported HTTP route handler modified in $file:$line
(export_statement
declaration: (function_declaration
name: (identifier) @fn_name (#match? @fn_name "^(GET|POST|PUT|DELETE|handler)$")
)
) @api_route_change

4. Detect Sensitive Config Alterations (C#)

Section titled “4. Detect Sensitive Config Alterations (C#)”
;; .symtrace/queries/config_classes.scm
;; @severity INFO
(class_declaration
name: (identifier) @class_name (#match? @class_name "Config$")
) @config_class_change
[ERROR] src/auth.rs:L42: Unhandled unwrap() detected in src/auth.rs:42: use proper error handling (Rule: no_unwrap)
[WARN] src/server.rs:L18: Security-sensitive API modified (Rule: security_api)
━━━ Summary ━━━
Files Scanned: 18 | Errors: 1 | Warnings: 1 | Passed: false

When .scm rules match modified functions in a diff, operations are annotated inline:

━━━ src/auth.rs
~ [MODIFY] function_item 'authenticate_user' modified (L42 -> L45) [80% similarity, medium]
── Custom Rule Alerts ──
⚠️ [ERROR] [security_api] Security-sensitive public API signature modified

Machine-Readable SARIF Output (--format sarif)

Section titled “Machine-Readable SARIF Output (--format sarif)”
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "symtrace-lint",
"semanticVersion": "0.5.0"
}
},
"results": [
{
"ruleId": "no_unwrap",
"level": "error",
"message": {
"text": "Unhandled unwrap() detected in src/auth.rs:42"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "src/auth.rs"
},
"region": {
"startLine": 42
}
}
}
]
}
]
}
]
}

Configure default query directories and evaluation flags in .symtracerc / symtrace.toml:

[queries]
enabled = true
dir = ".symtrace/queries"
fail_on_security_match = false # If true, --check exits with code 1 on security rule match