SlopScupper
00 crowd

shifty

Fast vibe-coded shacl validation+inference
Open repo on GitHub Open the demogithub.com/gtfierro/shifty
Rust · ★ 8 · 0 forks · BSD-3-Clause · paperwork by the Cap'mmostly ai (inferred)light human (inferred)works-on-my-machine (inferred)other
listed 9 hours ago by gtfierro · last checked 1 hour ago
The owner didn't write this. This repo never submitted itself. The Cap'm found it on a truffle trawl and wrote its paperwork from what GitHub already shows. Picked by hand by the Cap'm on 2026-09-11: a SHACL validation and inference engine in Rust with Python and WebAssembly builds, described as "Fast vibe-coded shacl validation+inference". 8 stars; BSD-3-Clause license. The owner did not submit this. Votes count; awards don't until the owner claims it.

I'm not calling your project slop! Geeze, it's a joke... Do you own this repo?

Log in with GitHub as gtfierro. There's no account to make: SlopScupper only asks GitHub who you are (read:user), never sees your code, and keeps just your id, login and avatar. Then you can:

  • Keep it, on your terms. Commit your own slopscore.md (spec) and press Refresh. Your paperwork replaces the Cap'm's, and you can submit it for Slop of the Day.
  • Take it down. One click on Remove. It stays gone; the trawl never brings it back.

Log in with GitHub

Can't log in as the owner? Request a takedown. No login needed, and a trawled listing comes down right away.

GitHub says
Fast vibe-coded shacl validation+inference
website
https://shifty.gtf.fyi/
topics
inferencerdfshaclvalidation
created
2022-05-02 · pushed 4 days ago · 1213 commits · 3 contributors
release
v0.4.4 · 2026-09-02
languages
Rust 71%Python 20%C++ 4%JavaScript 2%Shell 1%C 1%
paperwork
contributinglicensereadme 57% health
dependencies
no dependency graph (no manifest, or disabled) · OSV.dev, checked 9 hours ago

Disclosures, inferred by the Cap'm

slopbucket
vibe-coded
category
other
ai_generated
mostly
human_touch
light
status
works-on-my-machine
language (detected)
ccppcssjavascriptpythonrustshelltex
topic (detected)
inferencerdfshaclvalidation
license (detected)
bsd-3-clause

The Cap'm's log

The Cap'm wrote this paperwork, not the owner. This repo never submitted itself to SlopScore. The Cap'm picked it by hand: a SHACL validation and inference engine in Rust with Python and WebAssembly builds, described as "Fast vibe-coded shacl validation+inference". It carries the BSD-3-Clause license. The disclosures above are his best guess from what GitHub shows.

Is this yours? Commit a real slopscore.md and press Refresh to replace this, or remove the listing in one click. There's no account to make: you log in with GitHub.

README — the repo's own words, folded up so the grading fits on one screen

shifty

A formalism-first SHACL validation and SHACL-AF inference engine written in Rust, grounded in the algebraic treatment of Common Foundations for SHACL, ShEx, and PG-Schema (arXiv:2502.01295). Available as a command-line tool, Python bindings (pyshifty), a C++17 static-library SDK, and a WebAssembly module that runs in the browser.

See the archive-first-attempt branch for an older attempt, which was published as shifty 0.0.7

Disclosure: This project was nearly 100% "vibe coded" with Claude Opus 4.8, Sonnet 4.6, and ChatGPT 5.5

Features

  • Full SHACL Core validation — node and property shapes, all standard constraint components
  • SHACL-AF inference — forward-chaining sh:rule evaluation (Triple Rules, SPARQL Construct Rules) to a fixed point, with stratification analysis for recursive rulesets
  • Algebraic IR — shapes are lowered to a path algebra (π) and shape grammar (φ) before evaluation; the same IR drives both validation and inference
  • Native SPARQL execution — a subset of sh:sparql constraints and SPARQL Construct rules runs directly over an indexed dataset without a full SPARQL engine, with automatic fallback to Spareval for unsupported constructs
  • Multi-layer pipeline — parsing → algebraic lowering → normalization/CSE → physical planning → execution; each layer is independently inspectable
  • pyshifty-compatible Python APIvalidate() returns (conforms, report_graph, results_text) matching pyshifty's interface

Feature support

Legend: ✅ supported · ⚠️ partial / gated · ❌ unsupported.

SHACL Core

Feature Status Notes
Node & property shapes
Targets — targetNode, targetClass, targetSubjectsOf, targetObjectsOf, implicit class
Cardinality — minCount, maxCount
Value type — datatype, nodeKind, class
Range — min/maxInclusive, min/maxExclusive numeric, date/time, and duration ordering
String — minLength, maxLength, pattern (+flags), languageIn, uniqueLang
Logical — and, or, not, xone
Shape-based — node, property, qualifiedValueShape (+qualifiedMin/MaxCount, qualifiedValueShapesDisjoint)
Property pairs — equals, disjoint, lessThan, lessThanOrEquals on node and property shapes
Other — closed (+ignoredProperties), hasValue, in
Paths — predicate, inverse, sequence, alternative, zeroOrMore, oneOrMore, zeroOrOne
severity, deactivated, message

SHACL-AF (Advanced Features)

Feature Status Notes
Rules — sh:TripleRule, sh:SPARQLRule (CONSTRUCT) forward-chained to a fixed point with sh:order/sh:condition
Node expressions — sh:this, constants, sh:path, sh:filterShape, sh:intersection, sh:union, function application
SPARQL targets — sh:target + sh:select
SPARQL constraints — sh:sparql (sh:select / sh:ask) native execution with Spareval fallback
Custom constraint components — sh:parameter + sh:validator/sh:nodeValidator/sh:propertyValidator optional params, simple & complex $PATH; report path
Expression constraints — sh:expression
SHACL functions — sh:SPARQLFunction in node expressions full data-graph access
SHACL functions — sh:SPARQLFunction called from SPARQL (sh:sparql, CONSTRUCT, dash:expression) ⚠️ evaluated as pure functions of their arguments; a body that reads the data graph is gated (see on_unsupported)
JavaScript — sh:js*, sh:JSFunction no JS engine

Recursion & semantics

Feature Status Notes
Stratified recursive shapes gfp validation / lfp inference per stratum
Non-stratifiable schemas (cycle through negation) diagnosed and refused, never guessed

Feature-handling policy

Partially supported features are handled per an on_unsupported setting (EngineOptions in Rust; the on_unsupported= keyword on validate/validate_algebra/infer and PreparedValidator in Python):

  • "ignore" (default) — best-effort: e.g. a graph-reading function called from a SPARQL context is evaluated over an empty dataset (result may be unreliable).
  • "error" — fail loudly: the unsupported construct is refused so the failure surfaces (e.g. as a constraint error) instead of a silent wrong answer.

Malformed shapes are separate from on_unsupported: invalid lowering diagnostics, including malformed SPARQL or an unresolved query prefix, always raise an error before validation or inference. They never remove a constraint or rule from the schema.

conforms, report, text = shifty.validate(data, shapes, on_unsupported="error")

Installation

CLI

cargo install --path crates/shifty-cli

Or build from source:

cargo build --release -p shifty-cli
# binary at target/release/shifty

Python

pip install pyshifty

The package installs as pyshifty but is imported as shifty:

import shifty

To build from source (requires Rust and maturin):

cd python
pip install maturin
maturin develop

C++

The C++17 SDK embeds Shifty as a Rust static library and provides RAII wrappers for RDF loading, SPARQL queries, reusable SHACL validators, and evidence-carrying validation:

cmake -S cpp -B build/cpp
cmake --build build/cpp
ctest --test-dir build/cpp --output-on-failure
#include <shifty/shifty.hpp>

shifty::Dataset dataset;
dataset.load_file("data.ttl");

auto rows = dataset.query("SELECT ?s WHERE { ?s ?p ?o }");
auto validator = shifty::PreparedValidator::from_file("shapes.ttl");
auto report = validator.validate(dataset);

shifty::EvidenceSession evidence(validator, dataset);
for (const auto &statement : evidence.validate().statements()) {
    for (const auto &focus : statement.selected_foci) {
        std::cout << focus.focus_node << " " << focus.explanation << "\n";
    }
}

See cpp/README.md for installation, CMake package usage, and the scan-then-explain path for corpora where materializing all evidence is too expensive.

Browser / WebAssembly

The shifty-wasm crate compiles the engine to WebAssembly so the full inference

  • validation pipeline runs entirely in the browser — no server, no round-trips. It ships a framework-free playground (file upload + caching, rich report rendering, inference downloads), with all engine work on a Web Worker.
./crates/shifty-wasm/build.sh
python3 -m http.server -d crates/shifty-wasm   # open http://localhost:8000/example/

See crates/shifty-wasm/README.md for the JS API, build/rebuild instructions, and embedding details.

CLI usage

Validate

shifty validate --shapes shapes.ttl --data data.ttl
conforms: false
violations: 1
  <http://example.org/bob>  [target: ∃ rdf:type .⊤]
      - (ex:name) 123 → expected datatype xsd:string

Emit a W3C sh:ValidationReport in Turtle:

shifty validate --shapes shapes.ttl --data data.ttl --report

JSON output:

shifty validate --shapes shapes.ttl --data data.ttl --format json

Validation runs SHACL-AF rules to a fixed point by default. Skip rule inference when validating shapes directly:

shifty validate --shapes shapes.ttl --no-infer

Graph mode controls which triples are visible to path traversal and SPARQL evaluation:

# default: focus nodes from data; paths/SPARQL use data ∪ shapes
shifty validate --shapes shapes.ttl --data data.ttl --graph-mode union

# focus nodes and evaluation use data only
shifty validate --shapes shapes.ttl --data data.ttl --graph-mode data

# focus nodes and evaluation both use data ∪ shapes
shifty validate --shapes shapes.ttl --data data.ttl --graph-mode union-all

# validate only selected named shapes as top-level entry points
shifty validate \
  --shapes shapes.ttl \
  --data data.ttl \
  --shape-name http://example.org/PersonShape

--shape-name is repeatable and has the alias --entry-shape. Selected shapes are used only as entry points; referenced helper shapes are still evaluated normally.

Infer

Run SHACL-AF rules to a fixed point, then print the derived triples:

shifty infer --shapes rules.ttl --data data.ttl
inferred 3 triple(s):
  <http://example.org/r1> <http://example.org/area> "6"^^<http://www.w3.org/2001/XMLSchema#integer>
  ...

Inspect

Inspect how a shapes graph looks at each stage of the pipeline:

# Raw triples after parsing
shifty inspect --stage rdf shapes.ttl

# Lowered algebraic IR (φ/π notation)
shifty inspect --stage algebra shapes.ttl

# After normalization and common-subexpression elimination
shifty inspect --stage normalized shapes.ttl

# Stratification analysis (recursion detection)
shifty inspect --stage strata shapes.ttl

# Physical plan: focus sources + cost-ordered shape checks
shifty inspect --stage plan shapes.ttl

# SPARQL constraint capability: which queries run native vs. Spareval
shifty inspect --stage capability shapes.ttl

All stages support --format text (default), --format json; the algebra and normalized stages also support --format dot for Graphviz output.

Shapes files and data files may be local paths or HTTP/HTTPS URLs. Both --shapes and --data are repeatable to merge multiple files.

Python usage

import shifty

Validate (pyshifty-compatible)

shapes = """
@prefix sh:  <http://www.w3.org/ns/shifty#> .
@prefix ex:  <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ex:PersonShape a sh:NodeShape ;
    sh:targetClass ex:Person ;
    sh:property [
        sh:path ex:name ;
        sh:minCount 1 ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path ex:age ;
        sh:maxCount 1 ;
        sh:datatype xsd:integer ;
    ] .
"""

data = """
@prefix ex: <http://example.org/> .

ex:Alice a ex:Person ; ex:name "Alice" ; ex:age 30 .
ex:Bob   a ex:Person .
"""

conforms, report_graph, results_text = shifty.validate(data, shapes)
# conforms → False
# report_graph → rdflib.Graph with sh:ValidationReport
# results_text → human-readable summary

Graph inputs can be a string (Turtle text, local path, or HTTP(S) URL), bytes, pathlib.Path, or rdflib.Graph. Existing string paths are read from disk; a directory raises IsADirectoryError, and a missing RDF-looking filename such as shapes.ttl raises FileNotFoundError. Long or multiline strings are Turtle and are never probed as paths. The same policy applies to each list/tuple member. HTTP(S) URLs are fetched once; their format is inferred from the response content type or URL suffix. If shacl_graph is omitted or passed as None, shapes are expected to be embedded in the data graph. An explicitly supplied zero-triple shapes graph raises ValueError.

To validate a shapes graph against itself, pass it once. The embedded path parses and plans one graph without constructing separate data and shapes graphs:

result = shifty.validate_algebra("shapes.ttl", infer=False)
conforms, report_graph, results_text = shifty.validate("shapes.ttl", infer=False)

For repeated validation, prepare the shapes graph once:

validator = shifty.PreparedValidator(shapes)
result = validator.validate_algebra(data, infer=False)
conforms, report_graph, results_text = validator.validate(data)

pathlib.Path inputs are parsed directly by Rust. rdflib.Graph inputs are serialized as Turtle so namespace bindings required by SHACL-SPARQL queries and rules are preserved.

Validate with structured result

validate_algebra returns an AlgebraResult with typed Violation objects instead of an RDF report graph:

result = shifty.validate_algebra(data, shapes)
print(result.conforms)        # False
for v in result.violations:
    print(v.focus_node)       # IRI of the failing focus node
    print(v.statement_id)     # stable statement id
    print(v.constraint_id)    # statement-level algebra id shared with repair witnesses
    for r in v.reasons:
        print(r.message)      # human-readable failure description
        print(r.path)         # path that was checked, if applicable
        print(r.value)        # the offending value node
        print(r.constraint_kind)
        print(r.constraint.render)

Reason.constraint is the originating algebraic operator, not the SHACL source component name. Violation.statement_id and Violation.constraint_id identify the failed top-level statement; Reason.constraint_id identifies the specific nested algebra node that produced a validation cause.

To connect validation output to repair witnesses:

result = shifty.validate_algebra(data, shapes, infer=False)
session = shifty.RepairSession(shapes, data, infer=False)

witnesses = {
    (w.focus, w.statement_id, w.constraint_id): w
    for w in session.witnesses()
}

for v in result.violations:
    witness = witnesses.get((v.focus_node, v.statement_id, v.constraint_id))
    for r in v.reasons:
        if r.constraint_kind == shifty.ConstraintKind.Cardinality:
            print("count failure:", r.constraint.definition)
        elif r.constraint_kind == shifty.ConstraintKind.ClassMembership:
            print("class failure:", r.constraint.definition)
    if witness is not None:
        print(witness.repair_tree().explain())

Set infer=False when validation should not first run embedded SHACL-AF rules to a fixed point.

Evidence coverage

EvidenceSession returns a statement-oriented EvidenceRun. Every authored statement remains visible, including a target that selects no nodes; each selected focus contains exactly one tagged Satisfaction or Failure:

session = shifty.EvidenceSession(sha

Read the rest on GitHub

Scan report · 2026-09-11
  • Prohibited terms or links
  • Repository eligibility
  • slopscore.md paperwork
  • Content policy
  • Risk review

0 comments

log in to comment.

report this listinglog in to report