CLI: qvr¶
The qvr console script ships with the package as a thin wrapper
around the parser, constraint solver, and compiler. Subcommands:
qvr check FILES...¶
Parse, run the constraint solver, and compile every supplied
.qvr file. Emits structured diagnostics; exits 0 on full
success, 1 on any error.
Flags:
--json, emit a single JSON document on stdout containing the full diagnostic list. Suitable for CI / pre-commit hooks.
Diagnostic codes:
parse, tree-sitter rejected the source.compile, the compiler raised :class:CompileError.residuated_constraint, aTypeSlashpattern appears outside a residuated context.effect_constraint, aTypeEffectApplyreferences an effect whose name doesn't match the conventional pattern.bundle_unknown_member, abundledeclaration references a member that isn't a declared rule, schema, bundle, or built-in schema.io, file-system error (file not found, permission denied).
qvr migrate PATHS...¶
Lower .qvr source forward along the QVR grammar release chain.
The composer chains the adjacent-pair migrators defined in
quivers.cli.migrations so users do not
have to know the intermediate versions; pinning the boundary with
--from / --to selects a sub-chain when needed.
Flags:
--from VERSION, source revision in the chain (defaults to the most recent release).--to VERSION, target revision (defaults toHEAD).--dry-run, report which files would change without writing.--output DIR, write migrated copies underDIRinstead of overwriting the originals.
Directory arguments are walked recursively; individual .qvr
files may also be supplied. The migration tooling is built on the
in-tree panproto VCS at grammars/qvr/vcs/ so adding a new
release is purely additive to the migrations package.
qvr repl [FILE]¶
Start the interactive REPL. Without a file, opens an empty session; with a file, loads and elaborates it before dropping to the prompt. See REPL and Language Server.
qvr lsp¶
Run the Language Server over stdio. Editor extensions (VS Code, Zed, Neovim) invoke this; the protocol is LSP 3.17. See REPL and Language Server.
Module reference¶
cli
¶
Command-line entry points for quivers.
The main function is registered as the qvr console script
in pyproject.toml.
Subcommands:
qvr check FILES...— parse + compile every supplied.qvrfile, emitting structured diagnostics. Exits 0 on full success, non-zero when any file produces an error.qvr migrate --from VER --to VER PATHS...— lower.qvrsource files from one tagged grammar revision to another, via panproto migrations composed from the in-treegrammars/qvr/vcschain.
Output format: human-readable by default, structured JSON when
--json is supplied. Each diagnostic carries:
file: source path,line,col: 1-indexed source location,severity:"error","warning", or"note",code: stable diagnostic code (parse,compile,effect_constraint,residuated_constraint),message: human-readable description.
check
¶
qvr check — parse + compile .qvr files and report diagnostics.
Implementation
For each input file:
parse(source)is invoked;ParseErrorproduces acode="parse"diagnostic.Compiler(module).compile()is invoked;CompileErrorproduces acode="compile"diagnostic.- The constraint solver in
quivers.dsl.constraintswalks the parsed AST for residuated-universe and effect-typed-application well-formedness violations; each emits acode="residuated_constraint"orcode="effect_constraint"diagnostic.
Successful files emit no diagnostics; on success the human-readable
mode prints "OK file.qvr".
Exit codes:
0— every file compiled without diagnostics,1— at least one file produced anerrordiagnostic,2— usage / IO error.
Diagnostic
dataclass
¶
Diagnostic(file: str, line: int, col: int, severity: Severity, code: str, message: str)
One structured diagnostic message.
main
¶
main(files: list[str], *, json_output: bool = False) -> int
Run qvr check on a list of paths.
| PARAMETER | DESCRIPTION |
|---|---|
files
|
Paths to
TYPE:
|
json_output
|
When True, emit a single JSON document on stdout containing the full diagnostic list. When False (default), emit human-readable lines.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
int
|
Exit code. 0 on full success; 1 on any error diagnostic. |
Source code in src/quivers/cli/check.py
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |
migrate
¶
qvr migrate command.
Lowers .qvr source forward along the QVR grammar release chain
declared in quivers.cli.migrations.
Surface::
qvr migrate path/to/file.qvr [paths...]
qvr migrate --from v0.10.0 --to HEAD --dry-run docs/examples/source/
qvr migrate --output OUT_DIR --to HEAD path/to/file.qvr
--from defaults to the most recent release on the chain (the
penultimate entry of quivers.cli.migrations.CHAIN);
--to defaults to HEAD. Both must be members of
quivers.cli.migrations.CHAIN; the CLI composes the
intermediate adjacent-pair migrators automatically, so adding a new
release is purely additive to the migrations package.
--dry-run reports which files would change without writing
output. --output DIR writes migrated copies under DIR
instead of overwriting the originals.
MigrateError
¶
Bases: Exception
Raised by the migrate CLI on a recoverable user-facing error.
main
¶
main(args: Namespace) -> int
Entry point invoked by the top-level qvr dispatcher.
Returns 0 when every file migrated cleanly; 2 on invalid input.
Source code in src/quivers/cli/migrate.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | |
migrations
¶
Registry of structural one-hop .qvr source migrations.
Each adjacent-pair migrator is a callable bytes -> bytes built
on the panproto pipeline in quivers.cli.migrations._common:
parse with the source revision's tree-sitter parser, build the
target schema by walking the source parse tree and emitting target
vertices/edges/constraints, then emit canonical target bytes via
the target revision's emit_pretty. The third stage is grammar-
bound by panproto: a target schema that does not satisfy the target
grammar's rules cannot emit.
The CHAIN tuple lists releases in chronological order with
"HEAD" always last. Each adjacent pair (CHAIN[i], CHAIN[i+1])
must have a registered migrator in MIGRATORS.
compose_migration walks CHAIN between any two listed
releases and composes the intermediate hops into a single
bytes -> bytes callable.
To add the next release:
- Tag the release in git.
- Run
python grammars/qvr/vcs/build_schemas.pyandpython grammars/qvr/vcs/build_parsers.py. - Rename the current
v<latest>_to_headmigrator module tov<latest>_to_v<next>(it now migrates between two pinned revisions), and write a newv<next>_to_headcovering the next batch of grammar changes if any. - Append the new release to
CHAINand register the migrator(s) inMIGRATORS.
The qvr migrate CLI consumes compose_migration and is
agnostic to which pairs are registered.
BlameReport
dataclass
¶
BlameReport(rule: str, introduced_at_commit: str | None, introduced_at_tag: str | None, last_present_at_commit: str | None, last_present_at_tag: str | None)
Where in the grammar's history a rule first appeared (or was last seen).
DiffCoverageReport
dataclass
¶
DiffCoverageReport(from_ref: str, to_ref: str, added_rules: tuple[str, ...], removed_rules: tuple[str, ...], uncovered_removed: tuple[str, ...])
The schema diff between two revisions, classified against a hop's declared converter dispatch table.
uncovered_removed
instance-attribute
¶
uncovered_removed: tuple[str, ...]
Rules removed at the target revision that are also absent
from declared_converters. Each one is a source-side vertex
kind that the migrator's dispatch will silently pass through as
a structural clone — and emit_pretty will then either
misrender or drop. These are the actionable misses.
format
¶
format() -> str
Render the report for CLI display.
Source code in src/quivers/cli/migrations/_vcs.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
MigrationError
¶
Bases: Exception
Raised when the requested migration cannot be composed.
blame_kind
¶
blame_kind(rule: str) -> BlameReport
Report when a tree-sitter rule was introduced or removed in the grammar's VCS history. Used by the migrator's failure path to point the user at the specific release that needs a new converter.
Source code in src/quivers/cli/migrations/_vcs.py
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | |
diff_coverage
¶
diff_coverage(from_ref: str, to_ref: str, declared_converters: frozenset[str]) -> DiffCoverageReport
Compute the schema diff between from_ref and to_ref
in the VCS, classified against the set of source-side rule
names the migrator declares it can handle.
A rule appearing in from_ref's schema but not in
to_ref's is a "removed" rule. If a removed rule is a top-
level declaration kind that the migrator's
_DECL_CONVERTERS dict does not list, the migrator will
silently pass it through (likely producing incorrect output);
these surface in uncovered_removed.
Identity hops (where from_ref and to_ref share a
commit) report no diff.
Source code in src/quivers/cli/migrations/_vcs.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
commit_id
¶
commit_id(ref: str) -> str
Resolve a release name to its panproto VCS commit id. Cached.
Source code in src/quivers/cli/migrations/__init__.py
154 155 156 157 158 | |
vcs_coverage_report
¶
vcs_coverage_report() -> list[DiffCoverageReport]
Run the panproto-VCS-driven coverage check across every
adjacent pair in CHAIN. Each report carries the schema
diff and the set of removed source rules not covered by the
corresponding hop's SOURCE_RULE_COVERAGE.
Use this from qvr migrate --check (CLI) or from a CI test
to catch migrators that drift behind grammar changes.
Source code in src/quivers/cli/migrations/__init__.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | |
compose_migration
¶
compose_migration(from_ref: str, to_ref: str) -> _Migrator
Return a single bytes -> bytes callable that composes
every adjacent-pair migrator between from_ref and to_ref
on CHAIN.
Source code in src/quivers/cli/migrations/__init__.py
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | |
available_targets
¶
available_targets(from_ref: str) -> tuple[str, ...]
Return every revision reachable forward from from_ref on
CHAIN (inclusive of from_ref itself).
Source code in src/quivers/cli/migrations/__init__.py
277 278 279 280 281 282 283 | |