Install
$ agentstack add skill-01clauding-claude-ontology-skill-ontology ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Ontology Engineering for TypeScript
> "An ontology is an explicit specification of a conceptualization." > — Thomas R. Gruber, Stanford KSL, 1993
Overview
This skill teaches Stanford's 7-step ontology development methodology adapted for TypeScript + SQL domain modeling. It transforms unstructured domain knowledge into rigorous, typed data architectures.
Three theoretical pillars:
- Gruber 1993 — Defined ontology, Ontolingua translation architecture, 5 design criteria
- Noy & McGuinness 2001 — Systematized into 7-step Ontology 101 methodology
- Shen Xin 2025 — Applied to enterprise systems (Digital Intelligence Triad, ITPAO fractal)
Three fundamental rules:
- There is no single correct way to model a domain — the best solution depends on the application
- Ontology development is necessarily iterative
- Concepts should be close to real objects and relationships in your domain
When to Use
Use when:
- Designing a new domain data model (types, interfaces, database tables)
- Building a classification or taxonomy (skill categories, user levels, content types)
- Creating a knowledge base with typed entities and relationships
- Designing a multi-dimensional scoring or matching system
- Refactoring a growing type system that has become inconsistent
- Evaluating whether to use inheritance, composition, or discriminated unions
- Building enterprise AI systems that need structured domain knowledge
Don't use when:
- Simple CRUD with obvious entity shapes (just write the interface)
- Single-file utility functions with no domain modeling
- Performance optimization of existing models
- The domain is already well-modeled and stable
The 7-Step Process
Step 1: Determine Domain and Scope
Ontology concept: Competency questions define the boundary of what your model must represent.
Code equivalent: Write a list of questions your type system must answer. These become acceptance criteria.
Process:
- Define the domain in one sentence
- Write 5-10 competency questions the system must answer
- Identify what is explicitly OUT of scope
- Identify who uses and maintains this model
Example (Jyotish system):
Domain: Vedic astrology chart interpretation
Competency questions:
- Which planet rules a given zodiac sign? → Rashi.ruler: GrahaId
- Is Mars friendly to Jupiter? → Graha.friendlyPlanets: GrahaId[]
- What yogas are present with Mars in kendra? → YogaCondition with condition types
- What is compatibility score between charts? → Multi-dimensional Kuta scoring
Out of scope: Western astrology, daily horoscope text generation
Decision checkpoint: If you cannot write 5-10 competency questions, the domain is not well-enough understood. Brainstorm first.
Template:
Domain name: ___________
One-sentence purpose: ___________
Primary users: ___________
Competency Questions:
1. ___________ → Data requirement: ___________
2. ___________ → Data requirement: ___________
...
In Scope: ___________
Out of Scope: ___________
Might Add Later (v2): ___________
Step 2: Consider Reusing Existing Ontologies
Ontology concept: Check existing knowledge bases before building from scratch.
Checklist:
- [ ] Check
src/types/for existing type definitions - [ ] Check
src/data/for existing knowledge base files - [ ] Check database schema for existing tables
- [ ] Check npm ecosystem for domain-specific type packages
- [ ] Check open-source ontologies (schema.org, Dublin Core, etc.)
Rule: Reuse > Extend > Create from scratch.
Step 3: Enumerate Important Terms
Ontology concept: Brainstorm all domain concepts without organizing.
Process:
- List every domain term — don't organize yet
- Group loosely into nouns (entities), adjectives (properties), verbs (relationships)
Example:
Nouns (entities): User, Post, Comment, Draft, Tag, Community
Adjectives (props): published, archived, pinned, featured, deleted
Verbs (relations): publishes, comments-on, belongs-to, tags, votes-on
Step 4: Define Classes and Class Hierarchy
The is-a litmus test:
"Every [Child] is a [Parent]" must be TRUE
"Every [Parent] is a [Child]" must be FALSE
TypeScript mapping:
| Ontology Pattern | TypeScript Pattern | When to Use | |-----------------|-------------------|-------------| | Class hierarchy (is-a) | interface D extends B | Shared structure + specialization | | Disjoint siblings | Discriminated union | Mutually exclusive variants | | Abstract class | interface (not instantiated) | Shared contract only | | Multiple inheritance | type C = A & B (intersection) | Rare; prefer composition |
Critical rules:
- is-a only: Post is NOT a subclass of User (that's has-a)
- No cycles: If A extends B and B extends A → same thing, merge them
- Disjointness: Mutually exclusive siblings → discriminated union
- Sibling consistency: All siblings at same level of generality
- Minimum subclasses: 1 subclass = modeling problem; >12 = need intermediate categories
Decision tree — Union vs Extends vs Composition:
Are variants mutually exclusive?
YES → Use discriminated union: type T = A | B | C
NO → Do variants share most fields?
YES → Use extends: interface B extends A
NO → Use composition: type C = A & B
Example:
// Discriminated union (mutually exclusive content types)
type Content =
| { kind: 'post'; title: string; body: string }
| { kind: 'moment'; media: string; caption?: string }
| { kind: 'draft'; title: string; status: DraftStatus }
// Extension (shared base + specialization)
interface BaseEntity { id: string; createdAt: string; updatedAt: string }
interface Post extends BaseEntity { title: string; body: string; authorId: string }
// Composition (independent aspects)
type Timestamped = { createdAt: string; updatedAt: string }
type Authored = { authorId: string }
type Post = { id: string; title: string; body: string } & Timestamped & Authored
Step 5: Define Properties (Slots)
Key distinction:
- Intrinsic properties: Belong to the entity itself (title, name, status)
- Extrinsic properties: Come from relationships (authorId, communityId)
Rules:
- A property attaches to the MOST GENERAL class that has it
- If ALL instances share a property → it's on the base class
- If only SOME instances → it's on a subclass or variant
- Relationships are modeled as ID references, not nested objects
Example:
interface Post {
// Intrinsic
id: string
title: string
body: string
status: 'draft' | 'published' | 'archived'
// Extrinsic (relationships via ID)
authorId: string // → User
communityId: string // → Community
tagIds: string[] // → Tag[]
}
Step 6: Define Constraints (Facets)
Three-layer constraint alignment:
// Layer 1: TypeScript (compile time)
interface CreditAccount {
balance: number // must exist (not optional)
currency: Currency // type-constrained
}
// Layer 2: Zod (runtime validation)
const CreditSchema = z.object({
balance: z.number().min(0).max(999999), // range
currency: z.enum(['CNY', 'USD']), // domain
})
// Layer 3: SQL (storage)
// balance REAL NOT NULL DEFAULT 0 CHECK(balance >= 0)
// currency TEXT NOT NULL CHECK(currency IN ('CNY','USD'))
Constraint types: | Type | TypeScript | Zod | SQL | |------|-----------|-----|-----| | Required | Non-optional field | .min(1) / no .optional() | NOT NULL | | Optional | field?: Type | .optional() | nullable column | | Cardinality | T[] / T \| null | .array().min(1) | separate table | | Value range | Branded type | .min() / .max() | CHECK(...) | | Value domain | Union literal | .enum([...]) | CHECK(... IN ...) |
Step 7: Create Instances
Ontology concept: Populate the model with concrete data. Instances validate your type system.
Code equivalent: const data arrays and seed data.
Rule: If real data doesn't fit your types, the types need revision — not the data.
Example:
const GRAHAS: readonly Graha[] = [
{ id: 'surya', name: 'Sun', element: 'fire', nature: 'malefic' },
{ id: 'chandra', name: 'Moon', element: 'water', nature: 'benefic' },
{ id: 'mangal', name: 'Mars', element: 'fire', nature: 'malefic' },
] as const satisfies readonly Graha[]
// Validation: does every instance satisfy the interface?
// If not → revise the interface, not the data
Gruber's 5 Design Criteria
From Gruber, "A Translation Approach to Portable Ontology Specifications" (Stanford KSL-92-71, 1993):
1. Clarity
Intent: Definitions should be objective and formal, not depend on social context.
- ✅ Do: Use branded types for distinct concepts:
type UserId = string & { __brand: 'UserId' } - ❌ Don't: Use bare
stringfor everything
2. Coherence
Intent: Inferred conclusions must not contradict definitions.
- ✅ Do: Use exhaustive discriminated unions:
type Status = 'draft' | 'published' | 'archived' - ❌ Don't: Use
stringand hope runtime values match
3. Extendibility
Intent: New concepts can be defined using existing vocabulary without modifying existing definitions.
- ✅ Do: Add new union variant:
type Content = Post | Moment | Draft | Poll - ❌ Don't: Add
pollOptions?: PollOption[]to Post interface
4. Minimal Encoding Bias
Intent: Conceptual definitions should not depend on encoding choices.
- ✅ Do:
role: 'admin' | 'member' | 'guest' - ❌ Don't:
role: 0 | 1 | 2 // what does 2 mean?
5. Minimal Ontological Commitment
Intent: Define only what is needed. Make as few claims as possible about the world.
- ✅ Do:
interface Post { id: string; title: string; body: string } - ❌ Don't:
interface Post { /* 50 optional fields for every possible future use */ }
Ontology → TypeScript Mapping (Core)
| Ontology Concept | TypeScript Equivalent | Example | |-----------------|----------------------|---------| | Class | interface / type | interface User { ... } | | Subclass (is-a) | Union variant | { kind: 'admin'; permissions: string[] } | | Property (slot) | Interface field | title: string | | Facet (constraint) | Zod schema / branded type | z.string().min(1).max(200) | | Instance | const data / seed row | { id: 'surya', name: 'Sun' } | | Enumeration | String literal union | 'draft' \| 'published' \| 'archived' | | Relation | Foreign key / ID reference | authorId: UserId | | Cardinality | Array / optional / required | tags: string[] (0..N) | | Domain | Interface that owns property | Post.title (not global) | | Range | Property value type | createdAt: ISO8601String | | Inverse relation | Bidirectional ID refs | Post.authorId ↔ User.postIds | | Transitive relation | Recursive type / graph | Category.parentId: CategoryId \| null | | Disjoint classes | Discriminated union | type Mode = 'silicon' \| 'carbon' | | Covering axiom | Exhaustive switch | All variants handled in switch | | Annotation | JSDoc / branded type name | /** @semantic Revenue */ |
Decision Trees
1. Union vs Extends vs Composition
Are the variants mutually exclusive?
├── YES → Discriminated union: type T = A | B | C
└── NO → Do they share >50% of fields?
├── YES → extends: interface B extends A
└── NO → Composition: type C = A & B
2. Enum vs String Literal vs Const Object
Does each value need associated data?
├── YES → Const object array: const ITEMS = [{ id, name, ... }] as const
└── NO → Are values known at compile time?
├── YES → String literal union: type T = 'a' | 'b' | 'c'
└── NO → Branded string: type T = string & { __brand: 'T' }
3. Intrinsic vs Extrinsic Property
Does the property make sense without any other entity?
├── YES → Intrinsic: put it on the interface directly
└── NO → It's a relationship
→ Does it reference a single entity?
├── YES → Foreign key: entityId: EntityId
└── NO → Junction table / array of IDs
Auto-Trigger Keywords
This skill activates automatically when it detects these patterns:
- "design a data model" / "define types for" / "build a taxonomy"
- "classification system" / "type hierarchy" / "knowledge graph"
- "refactor god interface" / "too many optional fields"
- "discriminated union or extends" / "interface vs type"
- "competency questions" / "domain modeling" / "ontology"
- "本体论" / "领域建模" / "类型层级" / "分类体系"
Pre-Implementation Checklist
Before implementing any domain model, verify:
- [ ] Step 1: 5+ competency questions written and answered
- [ ] Step 2: Searched existing codebase for reusable types
- [ ] Step 3: All domain terms enumerated (nouns/adjectives/verbs)
- [ ] Step 4: Class hierarchy passes is-a litmus test
- [ ] Step 4: Decision tree applied (union vs extends vs composition)
- [ ] Step 5: Properties attached to most general applicable class
- [ ] Step 5: Intrinsic vs extrinsic distinction clear
- [ ] Step 6: Three-layer constraints aligned (TS + Zod + SQL)
- [ ] Step 7: At least 3 realistic instances created and validated
- [ ] Gruber: All 5 design criteria checked
References
- Gruber, T. R. (1993). "A Translation Approach to Portable Ontology Specifications." Stanford KSL-92-71.
- Noy, N. F. & McGuinness, D. L. (2001). "Ontology Development 101: A Guide to Creating Your First Ontology." Stanford SMI-2001-0880.
- Shen, X. (2025). "本体论下的企业级系统架构设计" + "基于数字员工的合馈制体系."
- Stanford Protégé: https://protege.stanford.edu/
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: 01clauding
- Source: 01clauding/claude-ontology-skill
- License: MIT
- Homepage: https://clawpond.com/ontology-skill
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.