Agent Skills: Ducklake Categorical Model

Categorical modeling for DuckLake with ACSet schemas

UncategorizedID: plurigrid/asi/ducklake-categorical-model

Install this agent skill to your local

pnpm dlx add-skill https://github.com/plurigrid/asi/tree/HEAD/skills/ducklake-categorical-model

Skill Files

Browse the full folder contents for ducklake-categorical-model.

Download Skill

Loading file tree…

skills/ducklake-categorical-model/SKILL.md

Skill Metadata

Name
ducklake-categorical-model
Description
Categorical modeling for DuckLake with ACSet schemas

Ducklake Categorical Model

Version: 1.0.0 Status: Production Ready Created: 2025-12-21 Schema: DucklakeMentionGraph

Overview

Loads ACSet model from ecosystem integration and provides functions for categorical database operations, morphism verification, and GF(3)-based colorization.

Purpose

Enable categorical modeling of ducklake mentions:

  • ACSet instantiation (DucklakeMentionGraph schema)
  • Morphism composition verification
  • Path queries between objects
  • Deterministic GF(3) colorization

Data Sources

  • Primary: /Users/bob/ies/ducklake_acset_model_complete.json
  • Schema Definition: DucklakeMentionGraph (7 objects, 8 morphisms)
  • Julia Integration: Catlab.jl via ACSets.jl

ACSet Schema

Objects

  1. DucklakeMention - Individual mention instances
  2. Session - Claude conversation sessions
  3. Project - File system projects
  4. Timestamp - Temporal ordering
  5. SemanticCluster - Intent/semantic groups
  6. PhaseNode - Development phases
  7. ColorTrit - GF(3) color assignments

Morphisms

  1. belongs_to: DucklakeMention → Session
  2. in_project: DucklakeMention → Project
  3. temporal_order: DucklakeMention → Timestamp
  4. semantic_cluster: DucklakeMention → SemanticCluster
  5. phase_transition: DucklakeMention → PhaseNode
  6. color_assignment: DucklakeMention → ColorTrit
  7. session_to_project: Session → Project
  8. cluster_to_phase: SemanticCluster → PhaseNode

Composition Laws

compose(belongs_to, session_to_project) == in_project

Functions

instantiate_acset(objects: dict, morphisms: dict) -> ACSet

Create ACSet instance from objects and morphisms.

from julia import Julia, Main
jl = Julia(compiled_modules=False)
jl.eval('using Catlab, Catlab.CategoricalAlgebra')

acset = instantiate_acset(
    objects={
        "DucklakeMention": 18,
        "Session": 12,
        "Project": 3,
        "Timestamp": 18,
        "SemanticCluster": 5,
        "PhaseNode": 3,
        "ColorTrit": 18
    },
    morphisms={
        "belongs_to": [1, 1, 2, 2, 3, ...],  # 18 elements
        "in_project": [1, 1, 1, 2, 2, ...],
        "temporal_order": [1, 2, 3, 4, 5, ...]
    }
)

Returns: Catlab ACSet instance

Implementation:

import json
from pathlib import Path

def instantiate_acset(objects: dict, morphisms: dict):
    """Instantiate DucklakeMentionGraph ACSet"""

    # Load schema from Julia
    jl.eval('''
    using Catlab, Catlab.CategoricalAlgebra

    @present SchDucklakeMentionGraph(FreeSchema) begin
        DucklakeMention::Ob
        Session::Ob
        Project::Ob
        Timestamp::Ob
        SemanticCluster::Ob
        PhaseNode::Ob
        ColorTrit::Ob

        belongs_to::Hom(DucklakeMention, Session)
        in_project::Hom(DucklakeMention, Project)
        temporal_order::Hom(DucklakeMention, Timestamp)
        semantic_cluster::Hom(DucklakeMention, SemanticCluster)
        phase_transition::Hom(DucklakeMention, PhaseNode)
        color_assignment::Hom(DucklakeMention, ColorTrit)
        session_to_project::Hom(Session, Project)
        cluster_to_phase::Hom(SemanticCluster, PhaseNode)

        MentionText::AttrType
        ConfidenceScore::AttrType
        SemanticIntent::AttrType
        TritValue::AttrType
        TimestampValue::AttrType

        mention_text::Attr(DucklakeMention, MentionText)
        confidence_score::Attr(DucklakeMention, ConfidenceScore)
        semantic_intent::Attr(DucklakeMention, SemanticIntent)
        color_trit::Attr(ColorTrit, TritValue)
        timestamp_value::Attr(Timestamp, TimestampValue)
    end

    @acset_type DucklakeMentionGraph(SchDucklakeMentionGraph,
        index=[:belongs_to, :in_project, :temporal_order, :semantic_cluster]
    ){String, Float64, String, Int, Float64}
    ''')

    # Create instance
    Main.graph = jl.eval("DucklakeMentionGraph()")

    # Add parts
    for obj, count in objects.items():
        jl.eval(f"add_parts!(graph, :{obj}, {count})")

    # Set morphisms
    for morph, values in morphisms.items():
        for i, val in enumerate(values, 1):
            jl.eval(f"set_subpart!(graph, {i}, :{morph}, {val})")

    return Main.graph

verify_composition(m1: str, m2: str) -> bool

Verify morphism composition law.

valid = verify_composition("belongs_to", "session_to_project")
# Returns: True (composes to in_project)

Composition Rules:

  • belongs_to ∘ session_to_project = in_project
  • Invalid compositions return False

query_morphisms(source: str, target: str) -> list

Find all morphism paths from source to target.

paths = query_morphisms("DucklakeMention", "Project")
# Returns: [
#   ["in_project"],
#   ["belongs_to", "session_to_project"]
# ]

Algorithm: Breadth-first search through morphism graph

colorize_by_gf3(objects: list, seed: int) -> dict

Assign GF(3) colors deterministically.

colors = colorize_by_gf3(
    objects=["mention_1", "mention_2", "mention_3"],
    seed=0x6475636b6c616b65
)
# Returns: {
#   "mention_1": {"trit": -1, "color": "#2673D8", "gf3": 2},
#   "mention_2": {"trit": 0, "color": "#4FD826", "gf3": 1},
#   "mention_3": {"trit": 1, "color": "#D84F2C", "gf3": 0}
# }

Color Algorithm:

  1. SplitMix64 PRNG with golden angle
  2. Map to trit ∈ {-1, 0, +1}
  3. Generate OkLCH color (L, C, H)
  4. Convert to hex
  5. Verify GF(3) conservation: Σ trits ≡ 0 (mod 3)

Usage Example

from skills.ducklake_categorical_model import *

# Load temporal analysis data
with open("/Users/bob/ies/ducklake_temporal_analysis.json") as f:
    temporal = json.load(f)

# Build ACSet
mention_count = len(temporal["detailed_samples"])
session_count = len(temporal["session_analysis"]["sessions"])
project_count = len(temporal["project_distribution"]["projects"])

acset = instantiate_acset(
    objects={
        "DucklakeMention": mention_count,
        "Session": session_count,
        "Project": project_count,
        "Timestamp": mention_count,
        "SemanticCluster": 5,
        "PhaseNode": 3,
        "ColorTrit": mention_count
    },
    morphisms={
        "belongs_to": [s["sessionId"] for s in temporal["detailed_samples"]],
        "in_project": [s["project"] for s in temporal["detailed_samples"]],
        "temporal_order": list(range(1, mention_count + 1))
    }
)

# Verify composition
assert verify_composition("belongs_to", "session_to_project")

# Find paths
paths = query_morphisms("DucklakeMention", "Project")
print(f"Found {len(paths)} paths from DucklakeMention to Project")

# Colorize mentions
mention_ids = [f"mention_{i}" for i in range(1, mention_count + 1)]
colors = colorize_by_gf3(mention_ids, seed=0x6475636b6c616b65)

# Verify GF(3) conservation
trit_sum = sum(c["trit"] for c in colors.values())
assert trit_sum % 3 == 0, f"GF(3) conservation violated: {trit_sum} mod 3 ≠ 0"
print(f"GF(3) verified: Σ trits = {trit_sum} ≡ 0 (mod 3) ✓")

Skills Dependencies

  • acsets (ACSet instantiation and queries)
  • gay-mcp (SplitMix64 color generation)
  • spi-parallel-verify (GF(3) conservation verification)

Integration Points

  • Temporal Introspection: Map sessions to ACSet Session objects
  • Semantic Analyzer: Map intents to SemanticCluster attributes
  • Pattern Expansion: Query morphism paths for pattern discovery

Schema Statistics

  • Objects: 7
  • Morphisms: 8
  • Composition laws: 1
  • Attribute types: 5
  • Attributes: 5
  • Indexed morphisms: 4

GF(3) Color Distribution

For 18 mentions with balanced ternary:

  • RED (trit=1): 6 mentions
  • GREEN (trit=0): 6 mentions
  • BLUE (trit=-1): 6 mentions
  • Sum: 6×1 + 6×0 + 6×(-1) = 0 ≡ 0 (mod 3) ✓

Categorical Laws

Composition

∀ f: A → B, g: B → C:
  compose(f, g): A → C

Associativity

compose(compose(f, g), h) = compose(f, compose(g, h))

Identity

compose(id_A, f) = f = compose(f, id_B)

Example Queries

# Find all mentions in a session
session_id = 1
mentions = incident(graph, session_id, :belongs_to)

# Find project for a mention
mention_id = 5
project = graph[mention_id, :in_project]

# Verify composition
for m in 1:nparts(graph, :DucklakeMention)
    session = graph[m, :belongs_to]
    proj_direct = graph[m, :in_project]
    proj_composed = graph[session, :session_to_project]
    @assert proj_direct == proj_composed
end

GF(3) Distribution

This skill operates in the YELLOW (GF3=1) structural category:

  • ACSet schema definition
  • Morphism composition
  • Categorical database operations

Skill Type: Categorical Modeling Color: YELLOW Polarity: GF(3) = 1 Access Pattern: Read/Write ACSet instances