Skip to content

feat(shacl): SHACL SDNA Migration - Prolog to SHACL links parser#654

Merged
lucksus merged 102 commits intodevfrom
feat/shacl-sdna-migration
Feb 24, 2026
Merged

feat(shacl): SHACL SDNA Migration - Prolog to SHACL links parser#654
lucksus merged 102 commits intodevfrom
feat/shacl-sdna-migration

Conversation

@data-coasys
Copy link
Copy Markdown
Contributor

@data-coasys data-coasys commented Feb 4, 2026

SHACL SDNA Migration - Queryable Schema Links

Overview

This PR migrates AD4M's schema definition system (SDNA) from opaque Prolog strings to queryable W3C SHACL RDF links. This enables schemas to be stored, queried, and reasoned about using the same graph infrastructure as instance data.

Architecture

Link Structure (Named Property Shapes - Option 3)

┌─────────────────────────────────────────────────────────────────────────┐
│                         SHACL LINK STRUCTURE                            │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌──────────────────┐                                                   │
│  │   NodeShape      │                                                   │
│  │ recipe://Recipe  │                                                   │
│  └────────┬─────────┘                                                   │
│           │                                                             │
│           ├──────────────────────────────────────────────────────────┐  │
│           │ sh:targetClass                                           │  │
│           ▼                                                          │  │
│  ┌──────────────────┐                                                │  │
│  │  recipe://Recipe │ (the class being described)                    │  │
│  └──────────────────┘                                                │  │
│           │                                                          │  │
│           ├──────────────────────────────────────────────────────────┤  │
│           │ sh:property (one per property)                           │  │
│           ▼                                                          │  │
│  ┌────────────────────┐   ┌────────────────────┐                     │  │
│  │ recipe://Recipe    │   │ recipe://Recipe    │                     │  │
│  │       .name        │   │   .ingredients     │                     │  │
│  └─────────┬──────────┘   └─────────┬──────────┘                     │  │
│            │                        │                                │  │
│   ┌────────┴────────┐      ┌────────┴────────┐                       │  │
│   │ sh:path: name   │      │ sh:path: ingr.. │                       │  │
│   │ sh:datatype:xsd │      │ sh:class: Ingr  │                       │  │
│   │ sh:minCount: 1  │      │ ad4m:collection │                       │  │
│   │ ad4m:getter     │      │ ad4m:adder      │                       │  │
│   │ ad4m:setter     │      │ ad4m:remover    │                       │  │
│   └─────────────────┘      └─────────────────┘                       │  │
│                                                                      │  │
└──────────────────────────────────────────────────────────────────────┘  │
                                                                          │

Code Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                         CODE RELATIONSHIPS                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────┐            │
│  │                    TypeScript Layer                      │            │
│  │                                                          │            │
│  │  ┌──────────────┐    ┌──────────────┐                   │            │
│  │  │ SHACLShape   │    │  SHACLFlow   │   Data Classes    │            │
│  │  │  .toLinks()  │    │  .toLinks()  │   + Serialization │            │
│  │  │ .fromLinks() │    │ .fromLinks() │                   │            │
│  │  └──────┬───────┘    └──────┬───────┘                   │            │
│  │         │                   │                            │            │
│  │         ▼                   ▼                            │            │
│  │  ┌─────────────────────────────────────────┐            │            │
│  │  │         PerspectiveProxy                 │            │            │
│  │  │  .addShacl(shape)  .addFlow(flow)       │ Storage    │            │
│  │  │  .getShacl(class)  .getFlow(name)       │ Methods    │            │
│  │  └──────────────────────┬──────────────────┘            │            │
│  │                         │ GraphQL                       │            │
│  └─────────────────────────┼───────────────────────────────┘            │
│                            ▼                                            │
│  ┌─────────────────────────────────────────────────────────┐            │
│  │                      Rust Layer                          │            │
│  │                                                          │            │
│  │  ┌──────────────────────────────────────────┐           │            │
│  │  │         perspective_instance.rs          │           │            │
│  │  │  add_sdna() - entry point for schemas    │           │            │
│  │  │  Detects: Prolog vs SHACL JSON vs Links  │           │            │
│  │  └──────────────────────┬───────────────────┘           │            │
│  │                         │                               │            │
│  │         ┌───────────────┼───────────────┐               │            │
│  │         ▼               ▼               ▼               │            │
│  │  ┌────────────┐  ┌────────────┐  ┌────────────┐        │            │
│  │  │  Prolog    │  │  SHACL     │  │  Direct    │        │            │
│  │  │  Parser    │  │  JSON      │  │  Links     │        │            │
│  │  │  (legacy)  │  │  Parser    │  │  (new)     │        │            │
│  │  └─────┬──────┘  └─────┬──────┘  └─────┬──────┘        │            │
│  │        │               │               │                │            │
│  │        └───────────────┼───────────────┘                │            │
│  │                        ▼                                │            │
│  │              ┌─────────────────┐                        │            │
│  │              │  Shared Links   │  Stored in             │            │
│  │              │  (SurrealDB)    │  Perspective           │            │
│  │              └─────────────────┘                        │            │
│  └─────────────────────────────────────────────────────────┘            │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Data Flow

┌─────────────────────────────────────────────────────────────────────────┐
│                        SCHEMA STORAGE FLOW                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  Developer writes:                                                      │
│  ┌────────────────────────────────────────┐                            │
│  │  @SDNAClass({ name: "Recipe" })        │                            │
│  │  class Recipe {                        │                            │
│  │    @SubjectProperty()                  │                            │
│  │    name: string;                       │                            │
│  │                                        │                            │
│  │    @SubjectCollection()                │                            │
│  │    ingredients: Ingredient[];          │                            │
│  │  }                                     │                            │
│  └──────────────────┬─────────────────────┘                            │
│                     │                                                   │
│                     ▼                                                   │
│  ┌────────────────────────────────────────┐                            │
│  │  Decorator generates SHACLShape        │                            │
│  │  with targetClass, properties, etc.    │                            │
│  └──────────────────┬─────────────────────┘                            │
│                     │                                                   │
│                     ▼                                                   │
│  ┌────────────────────────────────────────┐                            │
│  │  perspective.addShacl(shape)           │                            │
│  │  → shape.toLinks() generates links     │                            │
│  │  → GraphQL mutation sends to Rust      │                            │
│  └──────────────────┬─────────────────────┘                            │
│                     │                                                   │
│                     ▼                                                   │
│  ┌────────────────────────────────────────┐                            │
│  │  Rust: add_sdna_links() stores as      │                            │
│  │  shared links in perspective           │                            │
│  └──────────────────┬─────────────────────┘                            │
│                     │                                                   │
│                     ▼                                                   │
│  ┌────────────────────────────────────────┐                            │
│  │  Links queryable via SurrealQL:        │                            │
│  │  SELECT * FROM links WHERE             │                            │
│  │    predicate = 'sh:property'           │                            │
│  └────────────────────────────────────────┘                            │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

Key Changes

TypeScript (core/)

File Purpose
shacl/SHACLShape.ts Shape class with toLinks()/fromLinks() serialization; constructor auto-derives shape URI
shacl/SHACLFlow.ts Flow (state machine) class with full serialization support
perspectives/PerspectiveProxy.ts addShacl(), getShacl(), addFlow(), getFlow() methods
Ad4mModel.ts Removed Prolog fallbacks — fully SHACL-native; fixed property filtering, collection instance checks, and falsy value handling
getSubjectClassMetadataFromSDNA.ts Rewritten to use link API; made public; SurrealDB query fixed (string::ends_with)
shacl/*.test.ts Comprehensive unit tests including toJSON/fromJSON round-trips

Rust (rust-executor/)

File Purpose
perspectives/shacl_parser.rs Prolog→SHACL links parser for backward compatibility; extract_namespace() fix
perspectives/perspective_instance.rs add_sdna() integration; SHACL-only subject class lookup; Prolog facts generated from SHACL links; ad4m://sdna link preserved for backward compat

Documentation

File Purpose
SHACL_SDNA_ARCHITECTURE.md Migration plan and phase documentation

Why This Matters

  1. Queryable Schemas: SHACL stored as links can be queried with SurrealQL
  2. Standards-Based: W3C SHACL enables tooling interoperability
  3. Evolvable: Change schemas without code changes
  4. Backward Compatible: Prolog SDNA automatically converted to SHACL links; Prolog facts generated on-the-fly from SHACL for legacy consumers
  5. SHACL is now the source of truth: Prolog code is no longer stored — only SHACL links are persisted

Migration Path

Phase Status Description
Phase 1 ✅ Complete TypeScript SHACL classes + storage
Phase 2 ✅ Complete Decorator integration
Phase 3 ✅ Complete Prolog→SHACL parser for backward compatibility
Phase 4 🔄 In Progress Deprecate Prolog — SHACL-only subject class lookup implemented; Ad4mModel fully SHACL-native; Prolog code storage removed

Notable Fixes

  • Subject instance creation and collection filtering — fixed edge cases in SHACL-based instance checks
  • Collection name double-pluralization — fixed in both SurrealDB queries and legacy SDNA paths
  • SHACLShape constructor — now auto-derives the shape URI, removing redundant shaclJson param
  • SDK addSdna() calls — now correctly pass SHACL JSON to the Rust backend
  • ad4m://sdna link storage restored — ensures backward compatibility with existing consumers
  • SurrealDB SHACL query — switched from CONTAINS to string::ends_with for correct class lookup
  • find_subject_class_from_shacl_by_query — aligned with actual SHACL link pattern
  • Rust test_extract_namespace — fixed compile error from Result not implementing PartialEq<&str>

Testing

  • ✅ TypeScript tests passing
  • ✅ Rust unit tests passing (cargo test)
  • ✅ Integration tests passing
  • cargo fmt clean

Usage Example

// New recommended way
const shape = new SHACLShape({
  targetClass: "recipe://Recipe",
  properties: [
    {
      path: "recipe://name",
      name: "name",
      datatype: "xsd:string",
      minCount: 1,
    },
  ],
});
await perspective.addShacl(shape);

// Legacy way (still works - auto-converts to SHACL links)
await perspective.ensureSDNASubjectClass(Recipe);

Summary by CodeRabbit

  • New Features

    • Full SHACL & flow support: define, store, enumerate, serialize/deserialize shapes and flows; model-level SHACL generation via new model export.
    • New APIs to add/get/list SHACL shapes and flows; optional SHACL JSON when adding SDNA; SHACL-driven action resolution.
  • Bug Fixes

    • Safer action parsing (no eval) and normalized link handling for consistent signing and retrieval.
    • Phase-3 shift to prefer SHACL-derived actions while preserving legacy query paths.
  • Tests

    • Extensive unit tests for shapes, properties, flows, actions, and round-trip serialization.
  • Documentation

    • New SHACL/SDNA architecture guide.

data-coasys and others added 30 commits January 30, 2026 23:30
- Create SHACLShape and SHACLPropertyShape classes
- Implement toTurtle() serialization (RDF Turtle format)
- Implement toLinks() for AD4M link-based storage
- Implement fromLinks() for reconstruction from Perspective
- Add implementation plan document

Part of SHACL SDNA migration (replacing Prolog with W3C standard)
- Import SHACLShape classes
- Add generateSHACL() method alongside generateSDNA()
- Convert property metadata to SHACL PropertyShapes
- Convert collection metadata to SHACL PropertyShapes
- Infer datatypes from TypeScript types and metadata
- Preserve AD4M-specific metadata (local, writable)
- Extract namespace from property predicates

Now @modeloptions decorated classes can generate both Prolog and SHACL
Track completed work and next steps for SHACL migration
- addShacl(): Store SHACL shapes as RDF links in Perspective
- getShacl(): Retrieve and reconstruct shapes from links
- getAllShacl(): Get all stored SHACL shapes
- Uses name -> shape URI mapping for easy retrieval
- Stores shapes as native RDF triples (link-based)

Enables storing and querying SHACL shapes alongside data
- Modified ensureSDNASubjectClass to generate both Prolog and SHACL
- Dual system now active: classes get both representations
- SHACL stored alongside Prolog SDNA in Perspective
- Backward compatible: Prolog still primary, SHACL additive

This completes the dual-system integration. Any @modeloptions class
automatically gets SHACL storage when added to a Perspective.
5 commits, ~950 lines added, dual system functional!
- Add extractNamespace() and extractLocalName() utility functions
- Add 'name' field to SHACLPropertyShape interface
- Modify toLinks() to generate named URIs ({namespace}{ClassName}.{propertyName})
  instead of blank nodes (_:propShape0)
- Maintains backward compatibility with fallback to blank nodes if name is missing
- Enables querying SHACL schemas with SurrealQL

Part of SHACL migration (Option 3: Named Property Shapes)
- Add property name to SHACLPropertyShape objects in decorators
- Enables generation of named URIs for property shapes
- Works for both regular properties and collections

Example: Recipe.name property generates URI 'recipe://Recipe.name'
instead of blank node '_:propShape0'
- Change 'new Literal(string)' to 'Literal.fromUrl(literal://string:...)'
- Fixes TypeScript build errors (TS2554)
- Literal constructor doesn't take arguments, must use static factory methods
- Verifies named URIs are generated instead of blank nodes
- Checks format: {namespace}{ClassName}.{propertyName}
- Example: recipe://Recipe.name instead of _:propShape0

Note: Requires full AD4M build to run due to dependencies
- Parse property name from named URI format ({namespace}{Class}.{name})
- Maintains backward compatibility with blank nodes
- Enables round-trip: toLinks() → fromLinks() preserves property names
Test was for manual validation only. Integration tests will
validate named shapes functionality properly.
Analyzes three options for SHACL storage and communication:
- Option A: Links all the way (recommended)
- Option B: Serialize to Turtle/JSON-LD string
- Option C: Hybrid approach

Recommendation: Keep current approach (links) for queryability.
Includes JSON Schema integration strategy and next steps.
- Created shacl_parser.rs with Option 3 (Named Property Shapes) implementation
- Modified add_sdna() to accept optional SHACL JSON parameter
- Parse SHACL JSON to RDF links using queryable URI structure
- Generate links: class definition + property shapes with full constraints
- Updated all add_sdna() call sites to pass None (backward compat)
- Added unit tests for namespace/localname extraction and basic parsing

Design:
- TypeScript generates both Prolog + SHACL JSON
- Rust stores Prolog (unchanged) + parses SHACL to links
- Dual system enables gradual migration
- SHACL links queryable via SurrealQL (unlike Prolog strings)

Next: Update TypeScript to generate and pass SHACL JSON
- Modified ensureSDNASubjectClass() to generate SHACL JSON from generateSHACL()
- Serialize SHACL shape to JSON with snake_case fields (Rust compat)
- Pass SHACL JSON through addSdna() → PerspectiveClient → GraphQL mutation
- Updated GraphQL mutation signature to accept optional shaclJson parameter
- Rust add_sdna() now receives SHACL JSON and parses to RDF links

Complete flow:
1. Decorator generateSHACL() creates SHACLShape object (already working)
2. ensureSDNASubjectClass() serializes to JSON
3. PerspectiveProxy → PerspectiveClient → GraphQL → Rust
4. Rust shacl_parser parses JSON → generates Option 3 links
5. Links stored in Perspective alongside Prolog SDNA

Result: Dual system operational, SHACL fully queryable via SurrealQL
Complete summary of SHACL migration work:
- 9 commits total (7 TypeScript + 2 Rust)
- ~1,500 lines added
- Dual system (Prolog + SHACL) operational
- Ready for testing

Next: Build, test, create PR
Breaking change: ensureSDNASubjectClass() now only uses SHACL
- Removed generateSDNA() call
- Pass empty string for Prolog SDNA (deprecated)
- Only generate and use SHACL JSON
- This will break code that relies on Prolog - GOOD, we need to find it

Next: Run tests, fix what breaks, complete migration to SHACL
- Clone name before use in parse_shacl_to_links()
- Remove unused after_scheme variable
- Handle URIs with no path correctly (recipe://Recipe -> recipe://)
- Handle fragment separators (#) for http://example.com/ns#Recipe
- Return just scheme:// when no path component exists

Note: Cannot test without Go toolchain (tx5-go-pion-sys dependency)
Key insight: Prolog SDNA serves TWO purposes:
1. Schema (properties, types, cardinality) ← SHACL replaces this
2. Behaviors (constructor, destructor, setters) ← SHACL CAN'T do this

SHACL is a constraint language, not a behavior/operation language.
Prolog's constructor/destructor/property/collection operations are
behaviors that have no SHACL equivalent.

Solution: Dual system is architecturally necessary
- Prolog: Defines behaviors (how to create/update instances)
- SHACL: Defines schema (queryable constraints)

This is the correct architecture. Tests should pass now.
Key insight: Dual system is architecturally necessary
- Prolog: Behaviors (constructor, destructor, operations)
- SHACL: Schema (queryable constraints, W3C standard)

SHACL is a constraint language, not operational. Cannot replace
Prolog's behavior definitions.

This is the correct, complete architecture.
…ncies

Breaking change: Now passes empty Prolog string to force failures

TODOs for complete Prolog removal:
1. Extract action definitions from generateSDNA():
   - constructor_actions (JSON array)
   - property_setter_actions per property
   - collection_adder/remover/setter per collection

2. Add action fields to SHACL JSON:
   {
     constructor_actions: [{action: 'addLink', ...}],
     properties: [{
       name, path, datatype, ...,
       setter_actions: [{action: 'setSingleTarget', ...}]
     }]
   }

3. Modify Rust shacl_parser to store actions as links:
   recipe://RecipeShape -> ad4m://constructor -> literal://string:[...]
   recipe://Recipe.name -> ad4m://setter -> literal://string:[...]

4. Replace Prolog queries in Rust:
   - get_constructor_actions: Query ad4m://constructor link
   - get_property_setter_actions: Query ad4m://setter link

This shows the path forward. Not complete yet.
Explains what's left to do:
1. Extract action definitions in TypeScript
2. Store as SHACL extension properties (ad4m://constructor, ad4m://setter)
3. Replace Prolog queries in Rust with link queries
4. Make tests pass

Asks for feedback on approach before continuing.
Shows:
- All SHACL links for complete class (Recipe example)
- W3C SHACL standard compliance (10 links)
- AD4M action extensions (5 links vs 1 manifest)
- Approach comparison (Multiple vs Manifest)
- Rust query examples for both approaches
- Recommendation: Approach 2 (27% fewer links, O(1) queries)
Key decisions:
- Separate links (not single manifest) for consistency
- Same pattern for Classes and Flows
- SurrealQL batch queries eliminate O(n) penalty
- Clear predicate semantics (ad4m://constructor, ad4m://onEntry, etc.)
- Generic Rust implementation pattern

Shows:
- Complete class action links
- Flow state machine action links
- SurrealQL batch query examples
- Unified action predicate vocabulary
- Migration strategy (Classes Phase 1, Flows Phase 2)
…perty operations

- Add AD4MAction struct in Rust SHACL parser for link operations
- Extend SHACLShape with constructor_actions and destructor_actions
- Extend PropertyShape with setter, adder, remover action arrays
- Update parse_shacl_to_links() to generate RDF links for all actions:
  - Shape-level: ad4m://constructor, ad4m://destructor
  - Property-level: ad4m://setter, ad4m://adder, ad4m://remover
- Fix extract_namespace() to handle AD4M-style and W3C-style URIs correctly
- Add comprehensive test for SHACL with actions parsing
- TypeScript decorators now generate SHACL shapes with full action definitions
- SHACLShape.toLinks() serializes actions as JSON literals in RDF links

This completes Phase 1 of SHACL migration - storing action definitions
as RDF links alongside W3C SHACL constraints.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2 of SHACL migration: Replace Prolog queries with SHACL link queries
for all action retrieval operations.

Rust changes (perspective_instance.rs):
- Add parse_actions_from_literal() for JSON parsing from literal:// format
- Add get_shape_actions_from_shacl() for constructor/destructor
- Add get_property_actions_from_shacl() for setter/adder/remover
- Add get_resolve_language_from_shacl() for property resolution
- Update get_constructor_actions() - SHACL first, Prolog fallback
- Add get_destructor_actions() - SHACL first, Prolog fallback
- Update get_property_setter_actions() - SHACL first, Prolog fallback
- Add get_collection_adder_actions() - SHACL first, Prolog fallback
- Add get_collection_remover_actions() - SHACL first, Prolog fallback
- Update resolve_property_value() - SHACL first for resolve language

TypeScript changes (PerspectiveProxy.ts):
- Add getActionsFromSHACL() helper for querying SHACL action links
- Update removeSubject() to try SHACL destructor before Prolog

Dependencies:
- Add urlencoding crate for URL-decoding literal values

Documentation:
- Consolidate 8 SHACL docs into single SHACL_SDNA_ARCHITECTURE.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ning

- Fix 3 places in SHACL query functions where get_links_local() returns
  Vec<(LinkExpression, LinkStatus)> but code iterated as Vec<LinkExpression>
- Add .normalize() before signing in 7 places to ensure signature
  verification works after storage (link data gets normalized on store)
- Critical bug: signatures were made on raw data but verified against
  normalized data, causing proof.valid to be false
Complete Phase 3 of SHACL migration by removing all Prolog fallbacks from SDNA operations. The system now uses W3C-standard SHACL exclusively for schema definitions and behavioral actions.

Changes:
- Remove get_actions_from_prolog() helper function and json5 dependency
- Simplify 6 SDNA functions to SHACL-only (remove context parameter):
  - get_constructor_actions()
  - get_destructor_actions()
  - get_property_setter_actions()
  - get_collection_adder_actions()
  - get_collection_remover_actions()
  - resolve_property_value()
- Update create_subject() call sites to match new signatures
- Update test_surreal_query_for_recipe_instances to use SHACL JSON

Benefits:
- Simpler architecture without Prolog dependency
- Clearer error messages indicating SHACL requirement
- All 236 tests passing (0 failed, 7 ignored)
- W3C-compliant schema definitions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…_shacl_to_links

- The link was being created both in add_sdna() and parse_shacl_to_links()
- When ensureSDNASubjectClass was called, getSdna() would find duplicates
  and count the same class twice
- Fix by only creating the link in add_sdna(), not in parse_shacl_to_links
- Update unit test expectations accordingly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
data-bot-coasys and others added 6 commits February 23, 2026 15:19
The client sends sdnaCode as String (nullable) since it's now optional
(SHACL is the primary source), but the resolver still declared it as
String! (non-null). This caused the addSdna test to fail with:
'Variable "$sdnaCode" of type "String" used in position expecting type "String!"'
- Use SHACLShape.toJSON() in ensureSDNASubjectClass instead of manual JSON (#15)
- Refactor getSubjectClassMetadataFromSDNA to use getShacl()/SHACLShape.fromLinks() (#14)
- Update addSdna docs to clarify SHACL is primary, Prolog kept for compat (#1)
- Mark Phase 3 as completed in architecture doc (#3)
- Add .worktrees/ to .gitignore
…, remove Prolog→SHACL code

Task 1: Add get_links_by_predicate_and_source_suffix to SurrealDBService and
convert 5 functions in perspective_instance.rs from get_links_local + ends_with
filtering to direct SurrealDB queries with string::ends_with.

Task 2: Rewrite sdnaFlows, availableFlows, startFlow, expressionsInFlowState,
flowState, flowActions, runFlowAction in PerspectiveProxy.ts to use
SHACLFlow/getFlow instead of Prolog infer calls.

Task 3: Remove parse_prolog_sdna_to_shacl_links function (328 lines) and its
test from shacl_parser.rs. Remove backward-compat Prolog→SHACL generation from
add_sdna. Keep shacl_to_prolog.rs (SHACL→Prolog direction).
lucksus
lucksus previously approved these changes Feb 23, 2026
…ide SHACL matching

- Remove buildQueryFromTemplate() from PerspectiveProxy.ts
- In createSubject/getSubjectData: extract className from object first,
  fall back to findClassByProperties() which queries SHACL links client-side
- Add findClassByProperties() that matches object properties/collections
  against SHACL shapes via link queries
- Remove find_subject_class_from_shacl_by_query() from Rust
- Remove get_shacl_properties_for_class/get_shacl_collections_for_class
  (no longer called)
- Simplify subject_class_option_to_class_name() to require className
- Remove unused collectionAdderToName/collectionRemoverToName/
  collectionSetterToName imports
Replace multiple round-trip link queries (fetch all classes, then per-class
property/collection queries) with a single SurrealDB query fetching all
relevant predicates at once. Process results in two passes client-side.

Also revert bootstrapSeed.json to dev branch version.
When className lookup fails or isn't available, fall back to
property-based matching via findClassByProperties() instead of
returning empty. Preserves original semantics of matching by
template structure, not just class name.
@data-bot-coasys data-bot-coasys force-pushed the feat/shacl-sdna-migration branch from 57e7a00 to 4e480bd Compare February 23, 2026 23:37
@lucksus lucksus merged commit 64fc4ec into dev Feb 24, 2026
5 checks passed
jhweir added a commit that referenced this pull request Feb 24, 2026
- Resolved 6 conflict blocks in PerspectiveProxy.ts (--ours as stable base)
- perspective_instance.rs auto-merged cleanly
- Replaced removed subjectClassesFromSHACL GraphQL endpoint with direct
  SHACL link queries in subjectClasses() and subjectClassesByTemplate()
- Ported findClassByProperties() from dev: single SurrealDB query matching
  SHACL property/collection shapes against template object prototype
@coderabbitai coderabbitai bot mentioned this pull request Feb 25, 2026
data-bot-coasys added a commit that referenced this pull request Feb 26, 2026
Major changes:
- social-dna.mdx: Replace Prolog-centric subject class documentation with
  SHACL-based approach. Add SHACL shape examples, link storage explanation,
  and SHACL constraint reference table. Mark Prolog as legacy.
- model-classes.mdx: Update 'Under the Hood' section to show generated SHACL
  instead of Prolog. Add SHACL-to-AD4M mapping table.

Reflects the completed SHACL SDNA migration (PR #654).
HexaField added a commit to HexaField/ad4m that referenced this pull request Feb 26, 2026
- SHACL is now the normative representation for Subject Classes
- Document SHACL link structure (sh:property, sh:path, sh:maxCount, etc.)
- Document AD4M SHACL extensions (ad4m://initial, ad4m://resolveLanguage, etc.)
- Add SHACL direct API (SHACLShape class)
- Add SurrealDB as recommended query engine
- Move Prolog to legacy/backward-compatibility section
- Add implementation requirements table (MUST/SHOULD/MAY)

Per review from @lucksus following SHACL SDNA migration (coasys#654, coasys#696).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants