linked-archi-query¶
Render and execute read-only SPARQL against an architecture graph. This owner holds the template catalogue, read-only enforcement, execution and the result envelope.
Exit codes: 0 answered, 1 refused (unsupported template, or not read-only), 2 error.
Exit 1 is a routing answer, not a crash: read the reason and use the named alternative.
An empty result is exit 0 - a finding, not a failure.
Command tree¶
la-query
├── catalog {list, show, dump, concerns}
├── query {render, run, literal, batch}
├── lint
├── doctor
└── _machine lint
Browsing the catalogue¶
python3 scripts/la-query catalog list --profile linked-archi-default --why
python3 scripts/la-query catalog show core/traceability --profile linked-archi-default
python3 scripts/la-query catalog dump --profile linked-archi-default \
--template core/neighbours-qualified --template core/dependents-qualified
python3 scripts/la-query catalog dump --profile linked-archi-default --stage analysis --notation bpmn
In catalog list, x marks a template this profile refuses, ! one that runs with a caveat, and
blank means available. --why explains every refusal and names an alternative.
catalog show is the authoritative parameter list — read it instead of the .rq file, because it
carries the typing, what the template does not prove, and its alternatives. Fields printed: name,
file, stage, notation, purpose, answers, does not prove, caveat, parameters,
requires (roles, graph roles, capability, membership), alternatives, then availability under the
named profile.
catalog dump retrieves full metadata for selected entries as JSON. Repeat --template to request
known candidates together; use --stage or --notation to narrow discovery. Repeated values of the
same filter match any value; different filter kinds must all match. For example, two --template
values select either template, while --stage analysis --notation bpmn selects only BPMN analysis
templates. Unknown filter values fail rather than silently returning a partial catalogue.
With --profile, each selected entry also carries available, unmet and profile_caveats.
la-analyse requests the entries needed to annotate its investigation plan. The schema_version: 1
payload and complete entry metadata remain the same with filters; without filters, catalog dump
still emits the whole catalogue. Prefer a selected dump when only a few templates are relevant.
For taxonomy-classification questions, la-analyse selects core/resolve-concept
before core/classified-by. The former searches SKOS names in the semantic graph
and returns candidate concept IRIs with schemes; review all exact candidates
and truncation before supplying CONCEPT_IRI. A taxonomy label is not a routing
instruction or an IRI.
Notation category questions use core/resolve-vocabulary-concept instead: it searches
attached SKOS schemes in the vocabulary graph, then core/elements-by-category
joins categories to instance types and returns the exact scheme on each row.
Viewpoint questions use core/viewpoint-catalog and core/viewpoint-detail to inspect
prescribed options; core/views separately reports actual model views. Neither a
catalog entry nor viewConformsToViewpoint proves SHACL conformance.
Project-owned catalogue extensions¶
A downstream skill may package a project-owned catalog.json and its .rq files,
as the fixed-graph example does. Packaging does not register the queries: pass the
catalogue explicitly to catalog list, show or dump, or to query render,
run or batch after installing the package with the agent-skills target:
python3 .agents/skills/linked-archi-query/scripts/la-query catalog show demo/accountability \
--catalog .agents/skills/fixed-graph-demo/assets/queries/catalog.json \
--profile .agents/skills/fixed-graph-demo/assets/profiles/demo.yaml
python3 .agents/skills/linked-archi-query/scripts/la-query query run demo/accountability \
--catalog .agents/skills/fixed-graph-demo/assets/queries/catalog.json \
--profile .agents/skills/fixed-graph-demo/assets/profiles/demo.yaml \
--data .agents/skills/fixed-graph-demo/assets/data/architecture.trig \
--set FOCUS_IRI=https://example.org/fixed-graph/catalog/element/payments-service
Run these from the consumer project after installing the example's pinned
v0.8.0 dependency. Publish that upstream tag before resolving the package.
--catalog is repeatable. Each extension uses the bundled catalogue's JSON schema, names its
own relative .rq files, and gives each template a project namespace such as acme/.
Duplicate names and file paths escaping the catalogue directory are refused; no working-directory
scan or automatic registration occurs. Use full names such as demo/accountability:
basename shortcuts can become ambiguous across catalogues. External entries go through the same
profile gates,
rendering, read-only check and result envelope as bundled entries. Keep project-specific fixture
tests with the extension: the upstream test floor covers bundled templates only. Treat the
catalogue path as a trust decision, not a sandbox for untrusted SPARQL, and keep endpoint
credentials read-only.
Registering a template does not add an la-analyse pattern or make the planner select it.
Analyse still investigates and orchestrates; it may inspect an explicitly supplied project
query, but only query executes it. The downstream APM example shows
the selected-skill package and the explicit graph/profile/catalogue choices together.
Model questions¶
The catalogue also reads the published question sets - core, ArchiMate 4.0 and ArchiMate
3.2 - which are the source of truth for the questions they hold: la-gram and the
deliverable generator ask the same ones. catalog list marks a question Q, and Q+T
where a template has its name too; then query run asks the question where the dataset
fits it and runs the template elsewhere, and the envelope's implementation says which
answered.
python3 scripts/la-query catalog concerns
python3 scripts/la-query catalog list --profile linked-archi-default --concern Completeness
python3 scripts/la-query query run notation/archimate/unrealised-capabilities \
--profile linked-archi-default --data model.trig \
--data archimate3.2-onto.ttl -o steps/unrealised-capabilities.json --preview
A question is written for one graph - the model and its metamodel together - so it reads
the dataset as one graph: on local data query run arranges that, each triple counted
once; an endpoint takes it only when the profile declares
capabilities.union_default_graph. What its query reads is gated like a template's
requires. One that reads the metamodel is checked when it runs, and refused - naming the
published Turtle to load with another --data - when the metamodel is not there, unless
its template can answer instead. A project's own question set joins with
--catalog questions.ttl. See the
template contract.
Generating SPARQL without execution¶
For a known profile and template, inspect its parameter contract and render it directly:
python3 scripts/la-query catalog show core/neighbours-qualified --profile linked-archi-default
python3 scripts/la-query query render core/neighbours-qualified --profile linked-archi-default \
--set FOCUS_IRI=https://example.org/la/bpmn/order-fulfillment/element/Task_Payment -o neighbours.rq
Rendering checks typed parameters, profile capability gates and query safety without opening a dataset. It produces candidate SPARQL, not findings about a graph. Question investigation, orientation, evidence review and orchestration belong to linked-archi-analyse; they are not prerequisites for generating a requested query. Resolve an unknown identifier before execution rather than inventing it from a label.
Running a query¶
flowchart LR
T["template name<br/>+ --set params"] --> R["render<br/><small>roles, graph scope, prefixes,<br/>membership, limits</small>"]
P["resolved profile<br/><small>via la-profile</small>"] --> R
R --> G{"gating<br/>verdict"}
G -->|refused| X["exit 1, reason<br/>+ alternative"]
G -->|"available<br/>or caveat"| L["validate_readonly"]
L --> E["la-connect<br/>_machine execute"]
E --> V["envelope<br/><small>rows + citation + caveats</small>"]
| Subcommand | Purpose |
|---|---|
query render <template> |
Print the rendered SPARQL. --force renders a refused template for inspection only. |
query run <template> |
Render, lint, execute, print the envelope. |
query literal --query/--file |
The same for an ad-hoc query. Cited as ad-hoc query. |
query batch <manifest> |
Several queries from a JSON manifest, one store load. |
Flags on run and literal (--set applies to run only):
| Flag | Default | Purpose |
|---|---|---|
--profile NAME_OR_PATH |
linked-archi-default |
Which profile to render against. |
--set NAME=VALUE |
— | Repeatable. Template parameter. An IRI works with or without angle brackets. |
--format {tsv,md,json} |
tsv |
How to print. |
--json |
off | The same as --format json. --format wins if both appear. |
--limit N |
100 |
Rows to print. A display cap only. |
-o, --output FILE |
stdout | Writes the envelope as JSON regardless of --format. |
--preview |
off | With -o, also print a bounded preview with caveats and citation. |
--limit is not the query's limit
--limit bounds what is printed. It does not bound the query, the work, or what -o and
--json write. The query's own cap is --set LIMIT=N, and hitting it is what sets truncated.
Save evidence and inspect it in one call¶
python3 scripts/la-query query run core/inventory-summary --data architecture.trig \
-o steps/inventory.json --preview --limit 20
For run and literal, --preview requires -o and a positive --limit; invalid combinations
are refused before profile resolution or query execution. The file retains the full JSON envelope,
including the query, every returned row, warnings, truncation and provenance. The preview uses TSV
regardless of --format or --json, and displays at most --limit rows with the existing caveats,
truncation warning and citation. ASK and empty results retain their existing guidance. CONSTRUCT
previews limit physical output lines and warn when the displayed fragment is not a complete RDF
document; the saved triples remain intact.
Without --preview, -o keeps its existing behavior: save the envelope and print the file location.
Saving all returned rows does not make a query capped by LIMIT complete; its truncated warning
still applies.
query batch¶
A manifest with schema_version: 1 and a non-empty queries array; each entry takes exactly one of
template, file or query, plus optional id, set and out. One store load serves them all.
{
"schema_version": 1,
"queries": [
{"id": "models", "template": "core/models", "out": "steps/models.json"},
{"id": "inventory", "template": "core/inventory-summary", "out": "steps/inventory.json"}
]
}
Save that manifest as batch.json, then:
python3 scripts/la-query query batch batch.json --data architecture.trig --preview --limit 20 \
-o batch-summary.txt
Each manifest out saves that result's complete JSON envelope. Batch -o saves the run summary,
not an envelope or the previews. --preview additionally prints each result's bounded evidence,
caveats and citation to stdout, even when the summary is saved. Batch previews do not require -o;
use manifest out entries to retain evidence for la-analyse bundle. Without --preview, batch
output remains the summary. --limit is per preview and does not change query limits or saved data.
Batch independent queries whose parameters are already known. Investigations use
la-analyse plan --batch-dir DIR to prepare eligible manifests; review prerequisite results before
running later groups, and run each batch instead of its individual commands. Analyse plans and
orchestrates; query owns execution, safety checks and envelopes.
lint¶
The first move on a hand-written query that returned nothing: far more often broken than evidence of absence.
With --data it also checks the path against the published SHACL — see
the path check. Only a non-read-only query, or missing
input, exits 1; an impossible path reports and exits 0.
The four things that break naive SPARQL here¶
These are the reasons the templates exist, and the reasons a hand-written query usually returns nothing.
1. The qualified form is the default. A relationship is a resource, not a triple. There is no
?a am:serves ?b unless the converter was run with --emit-direct-rel-triples:
2. Graph scope is mandatory. Concepts, views, provenance and model resources live in different
named graphs, and the default graph is not their union. A query with no GRAPH clause returns
nothing on a graph-partitioned dataset — and a query with one returns nothing on a flattened
Turtle export. The templates render the right shape from the profile's layout.
3. Direction matters and fails silently. Reversing arch:source and arch:target returns no
rows rather than an error.
4. A label is not an identifier. IRIs are minted as
{base}{notation}/{modelId}/element/{localId} and the local id is the source tool's. Never
construct one from a label; resolve it with core/resolve-element.
Never substitute something else for a query¶
The point of this skill is that an answer is attributable: a named template, a rendered query, a dataset identity, a profile version. Anything that bypasses that loses all of it.
- Do not grep the RDF.
grepon a.trigfile cannot resolve a label to an IRI, cannot scope to a graph, and produces no provenance. - Do not load the graph with another RDF library to answer a question. That skips read-only enforcement, profile resolution and the envelope.
- Do not search the repository for facts the graph is supposed to supply.
If the tooling cannot be resolved, say so and stop — la-query doctor names what is missing. If no
dataset is attached, report that rather than looking for one.
Environment¶
| Variable | Effect |
|---|---|
LINKED_ARCHI_DATA |
Dataset used when neither --data nor --endpoint is given. |
LINKED_ARCHI_STORE |
Store mode when --store is unset. |
LINKED_ARCHI_SKILLS_DIR |
Authoritative companion root. |
LINKED_ARCHI_LOCAL_DEADLINE_S |
Seconds ceiling on local execution. Default 300. |
LINKED_ARCHI_LOCAL_MAX_RSS_MB |
Memory ceiling for local execution, scaled by input size. |