Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ _build/
log/
.idea/
.claude/settings.local.json
.claude/worktrees/
rebar3
.wolf/
.claude/settings.local.json
CLAUDE.local.md
resume
21 changes: 11 additions & 10 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,32 @@ SPDX-License-Identifier: GPL-2.0-or-later

| Component | State |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Build | Compiles clean — zero warnings (OTP 27 / rebar3 3.24) |
| `nref` subsystem | Fully implemented; DETS-backed; `set_floor/1` API |
| Build | Compiles clean — zero warnings (Erlang/OTP, the Open Telecom Platform, version 27 / rebar3 3.24) |
| `nref` subsystem | Fully implemented; backed by DETS (Disk-based Erlang Term Storage); `set_floor/1` API |
| `dictionary_imp` | Implemented; not yet wired to `dictionary_server` / `term_server` |
| `graphdb_bootstrap` | Implemented — Mnesia schema, table creation, scaffold loader |
| `graphdb_mgr` | Implemented — bootstrap startup, read API, category guard, cache audit/repair. Write-side delegation pending. |
| `graphdb_attr` | Implemented — attribute library (name, literal, relationship attributes) |
| `graphdb_class` | Implemented — taxonomic hierarchy with multi-parent inheritance (BFS DAG walk, H3) |
| `graphdb_class` | Implemented — taxonomic hierarchy with multi-parent inheritance (BFS — breadth-first search — over a DAG, a directed acyclic graph; H3) |
| `graphdb_instance` | Implemented — compositional hierarchy + four-level inheritance with multi-class membership (H4) and ambiguity-detecting class resolver (H5) |
| `graphdb_rules` | Stub |
| `graphdb_language` | Stub |
| Tests | 218 passing (154 Common Test + 64 EUnit) |
| Tests | 228 passing (164 Common Test + 64 EUnit) |

The kernel is functional under multi-inheritance and multi-class-
membership semantics. Template features beyond the connection-arc
scope AVP (M7) and multilingual support (M6) remain open; see §10.
scope AVP (an attribute-value pair stored on a node or relationship
row; M7) and multilingual support (M6) remain open; see §10.

---

## 2. Storage

| Subsystem | Storage | Why |
| ---------------------------------- | -------------------------- | --------------------------------------------------------- |
| `graphdb_*` (nodes, relationships) | **Mnesia** (`disc_copies`) | ACID across tables, secondary indexes, distribution-ready |
| `nref_allocator` / `nref_server` | DETS | Simple persistent counter; no relational query needs |
| `dictionary_imp` | ETS + `tab2file` | In-memory cache, persistent serialisation |
| Subsystem | Storage | Why |
| ---------------------------------- | ------------------------------------------------ | --------------------------------------------------------- |
| `graphdb_*` (nodes, relationships) | **Mnesia** (`disc_copies`) | ACID across tables, secondary indexes, distribution-ready |
| `nref_allocator` / `nref_server` | DETS | Simple persistent counter; no relational query needs |
| `dictionary_imp` | ETS (in-memory Erlang Term Storage) + `tab2file` | In-memory cache, persistent serialisation |

### Mnesia tables

Expand Down
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ SPDX-License-Identifier: GPL-2.0-or-later

# SeerStoneGraphDb

A distributed graph database written in Erlang/OTP, originally authored by
Dallas Noyes (SeerStone, Inc., 2008). Dallas passed away before completing the
project. The goal is to finish and extend his work. PRs are welcome. Treat this
codebase with care — preserve Dallas's style and conventions wherever possible
when completing NYI stubs.
A distributed graph database written in Erlang/OTP (the Open Telecom
Platform), originally authored by Dallas Noyes (SeerStone, Inc., 2008).
Dallas passed away before completing the project. The goal is to finish
and extend his work. PRs are welcome.

### Current Status

Expand All @@ -19,17 +18,17 @@ underway:

| Component | Status |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nref` subsystem | Fully implemented (DETS-backed ID allocator with `set_floor/1`) |
| `nref` subsystem | Fully implemented (DETS — Disk-based Erlang Term Storage — backed ID allocator with `set_floor/1`) |
| `dictionary` subsystem | `dictionary_imp` implemented; server stubs not yet wired (Task 7) |
| `graphdb_bootstrap` | Fully implemented — Mnesia schema/table creation, bootstrap scaffold loader (31 nodes, 30 relationship pairs) |
| `graphdb_bootstrap` | Fully implemented — Mnesia (Erlang's built-in distributed database) schema/table creation, bootstrap scaffold loader (31 nodes, 30 relationship pairs) |
| `graphdb_mgr` | Implemented — bootstrap init, public read API (`get_node`, `get_relationships`), category immutability guard, cache audit/repair (`verify_caches/0`, `rebuild_caches/0`); write operations delegate to workers |
| `graphdb_attr` | Fully implemented — attribute library (name, literal, relationship attributes, relationship types) |
| `graphdb_class` | Fully implemented — taxonomic hierarchy with multi-parent inheritance (BFS DAG), qualifying characteristics, class-level inheritance |
| `graphdb_class` | Fully implemented — taxonomic hierarchy with multi-parent inheritance (BFS — breadth-first search — over a DAG, a directed acyclic graph), qualifying characteristics, class-level inheritance |
| `graphdb_instance` | Fully implemented — compositional hierarchy, multi-class membership, four-level inheritance with class-resolver ambiguity detection |
| `graphdb_rules` | Gen_server stub — deferred to Enhancements (pattern recognition, relationship constraints) |
| `graphdb_language` | Gen_server stub — next to implement (Task 6) |

**218 tests** (64 EUnit + 154 Common Test) — all passing. See
**228 tests** (64 EUnit + 164 Common Test) — all passing. See
`TASKS-MEDIUM.md` and `TASKS-LOW.md` for the prioritised task list
(organised by severity).

Expand Down Expand Up @@ -80,7 +79,7 @@ SeerStoneGraphDb/
│ ├── seerstone/ # Top-level OTP application and supervisor
│ ├── database/ # database application (supervises graphdb + dictionary)
│ ├── graphdb/ # Graph database application and workers
│ ├── dictionary/ # ETS/file-backed key-value dictionary application
│ ├── dictionary/ # In-memory (ETS — Erlang Term Storage) and file-backed key-value dictionary
│ └── nref/ # Globally unique node-reference ID allocator
├── rebar.config # rebar3 umbrella build configuration
├── Makefile # Convenience targets (compile, shell, release, clean)
Expand Down Expand Up @@ -150,7 +149,8 @@ domain-specific behavior lives in the ontology; the kernel contains none of it.
### Node Types

Every entity in the system — class, attribute, rule, template, or instance — is a
**concept node** with a stable, unique identity (an Nref).
**concept node** with a stable, unique identity called an **Nref** (node
reference number — a positive integer allocated by the `nref` subsystem).

| Type | Where defined | Description |
| ------------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
Expand Down Expand Up @@ -230,17 +230,17 @@ Priority order — each step applies only to attributes not yet resolved by a hi
./rebar3 eunit --app=graphdb && ./rebar3 ct
```

| Suite | Type | Tests | Coverage |
| ------------------------- | ----- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `graphdb_bootstrap_tests` | EUnit | 37 | Term parsing, validation, record conversion |
| `graphdb_mgr_tests` | EUnit | 9 | Direction validation, client-side arg checks |
| `graphdb_class_tests` | EUnit | 11 | `is_valid_parent_kind/1`, `collect_qc_nrefs/2` |
| `graphdb_instance_tests` | EUnit | 7 | `find_avp_value/2` |
| `graphdb_bootstrap_SUITE` | CT | 17 | Full bootstrap load, Mnesia tables, idempotency, error handling |
| `graphdb_mgr_SUITE` | CT | 23 | Bootstrap init, read ops, category guard, write stubs, cache audit/repair |
| `graphdb_attr_SUITE` | CT | 17 | Attribute create/lookup, seeding, relationship types, atomic reciprocal pair (M4) |
| `graphdb_class_SUITE` | CT | 44 | Class create, QC, lookups, hierarchy, multi-inheritance (H3), inheritance, templates |
| `graphdb_instance_SUITE` | CT | 53 | Instance create, relationships (incl. M3 validation, M5 per-arc AVPs), lookups, hierarchy, four-level inheritance, multi-class membership (H4 + H5) |
| Suite | Type | Tests | Coverage |
| ------------------------- | ----- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `graphdb_bootstrap_tests` | EUnit | 37 | Term parsing, validation, record conversion |
| `graphdb_mgr_tests` | EUnit | 9 | Direction validation, client-side arg checks |
| `graphdb_class_tests` | EUnit | 11 | `is_valid_parent_kind/1`, `collect_qc_nrefs/2` |
| `graphdb_instance_tests` | EUnit | 7 | `find_avp_value/2` |
| `graphdb_bootstrap_SUITE` | CT | 17 | Full bootstrap load, Mnesia tables, idempotency, error handling |
| `graphdb_mgr_SUITE` | CT | 23 | Bootstrap init, read ops, category guard, write stubs, cache audit/repair |
| `graphdb_attr_SUITE` | CT | 17 | Attribute create/lookup, seeding, relationship types, atomic reciprocal pair (M4) |
| `graphdb_class_SUITE` | CT | 44 | Class create, QC (qualifying characteristics), lookups, hierarchy, multi-inheritance (H3), inheritance, templates |
| `graphdb_instance_SUITE` | CT | 53 | Instance create, relationships (incl. M3 validation, M5 per-arc AVPs — attribute-value pairs), lookups, hierarchy, four-level inheritance, multi-class membership (H4 + H5) |

Each CT test case runs in an isolated Mnesia database with a fresh nref
allocator in a private temp directory.
Expand Down
46 changes: 32 additions & 14 deletions TASKS-MEDIUM.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,38 @@ and `ARCHITECTURE.md` §3.

---

## M8. Attribute "type" (name vs. literal vs. relationship) is implied by parent subtree

**Spec:** §4 — *"The distinction between relationship attributes and
literal attributes is architecturally significant."*

**Evidence:** `graphdb_attr.erl:303-328`. The three `create_*_attribute`
paths put nodes under different parents (Names=6, Literals=7,
Relationships=8). The node carries no AVP marking its type. Inferring
the type at query time means walking the parent chain.

**Fix:** add an `attribute_type :: name | literal | relationship` AVP at
creation time, keyed by a new seeded `attribute_type` literal attribute.
Or add a dedicated field to the node record (smaller change to the
record set already touched by Critical tasks).
## M8. Attribute "type" (name vs. literal vs. relationship) is implied by parent subtree — RESOLVED

**Status:** Fixed via Option A (AVP-based marker).
`graphdb_attr` now seeds a fourth runtime literal attribute,
`attribute_type`, alongside `literal_type`, `target_kind`, and
`relationship_avp`. All four `create_*` paths stamp an
`#{attribute => attribute_type_nref, value => name|literal|relationship}`
AVP on the new node:

- `create_name_attribute/1` → `name`
- `create_literal_attribute/2` → `literal`
- `create_relationship_attribute/3` → `relationship` (on both
forward and reciprocal nodes)
- `create_relationship_type/1` → `relationship`

Bootstrap attribute nodes (nrefs 6-31) are retro-stamped at
`graphdb_attr:init/1` by walking the `parents` cache up to one of the
three top-level subtrees (Names=6, Literals=7, Relationships=8) — same
pattern as `ensure_template_avp_marker/1`. The retro-stamp is
idempotent across restarts.

New public API: `graphdb_attr:attribute_type_of/1` returns
`{ok, name | literal | relationship}` directly from the AVP without
walking the parent chain. `seeded_nrefs/0` now also reports the
`attribute_type` key.

Tests: 10 new CT cases under a new `attribute_type` group cover seed
exposure, AVP stamping on each create path, lookup correctness for
both runtime and bootstrap nodes, error paths, and retro-stamp
idempotence. Existing strict-equality AVP assertions in the
`creators` group were widened to `lists:member` checks to accommodate
the additional AVP.

---

Expand Down
Loading
Loading