Skip to content

TASKS-CRITICAL closeout: C1, C2, C3 — relationship kind, template kind, template scoping#9

Merged
david-w-t merged 14 commits intodavidwt-com:mainfrom
david-w-t:develop
May 7, 2026
Merged

TASKS-CRITICAL closeout: C1, C2, C3 — relationship kind, template kind, template scoping#9
david-w-t merged 14 commits intodavidwt-com:mainfrom
david-w-t:develop

Conversation

@david-w-t
Copy link
Copy Markdown
Contributor

Summary

Closes out TASKS-CRITICAL.md. Three schema-level changes that had to land before the database can carry live data, in execution order:

  • C1 (6c16e2b) — Add kind field to the relationship record (taxonomy | composition | connection | instantiation). Lets relationship-write paths discriminate the four spec-defined relationship types without pattern-matching on bootstrap nref constants.
  • C2 (9a43187) — Add template to the node kind atom set. The five-way enumeration is now category | attribute | class | instance | template.
  • C3 (17c3032) — Establish template scoping. Three subparts landed together:
    • C3a: bootstrap-seed the Template AVP attribute as nref 31 (parent: Instance Relationships); graphdb_attr:init/1 stamps the relationship_avp => true flag post-bootstrap.
    • C3b: graphdb_class:create_class/2 atomically writes the class node, taxonomy arcs, and a child default template node (kind = template, name "default"). New API: add_template/2, get_template/1, templates_for_class/1, default_template/1, class_in_ancestry/2.
    • C3c: graphdb_instance:add_relationship/4 auto-discovers the source's class default template; add_relationship/5 accepts an explicit TemplateNref. Both stamp #{attribute => 31, value => TemplateNref} on each direction of a Connection arc and validate that the template's parent class is in the taxonomic ancestry of the source's or target's class.

Per the new task-file retirement workflow, TASKS-CRITICAL.md ships in this PR with completion markers; the next PR opens with a commit that removes the file and cleans up doc references.

Test plan

  • rebar3 compile clean (zero warnings)
  • rebar3 ct — 115 Common Test cases, all green (was 94)
  • rebar3 eunit — 64 EUnit cases, all green (was 62)
  • Bootstrap counts updated: 31 nodes, 60 relationship rows
  • Tests cover: post-init Template AVP stamp + idempotency on restart; auto-default-template on class creation; explicit template; template-out-of-ancestry rejection; non-template-nref rejection; missing-default-after-delete behavior

🤖 Generated with Claude Code

david-w-t and others added 14 commits April 28, 2026 05:36
Replace knowledge-graph-database-guide.md references with
the-knowledge-network.md. Update "Environment database" →
"Ontology" and "Project database" → "Project (instance space)"
throughout both CLAUDE.md files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace "environment database" → "ontology" and "project database" →
"project (instance space)" in comments across graphdb_attr, graphdb_class,
and graphdb_mgr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…h-database-guide.md → the-knowledge-network.md, Environment/Project database → Ontology/Project)
Split outstanding work into four files by severity, drop completed
tasks, and re-prioritise based on the audit against
the-knowledge-network.md:

- TASKS-CRITICAL.md (C1, C2): schema-level — add template_nref and
  kind fields to the relationship record. Land before live data.
- TASKS-HIGH.md (H1-H5): correctness bugs in inheritance and class
  membership. resolve_from_class doesn't walk the class taxonomy
  (H4); Priority 4 double-walks higher priorities (H5); single
  inheritance and single class membership (H1, H2, H3).
- TASKS-MEDIUM.md (M1-M8 + Task 6 + E1): semantic departures, the
  query language, multilingual support, templates, and the rules
  engine.
- TASKS-LOW.md (L1-L5 + Task 7 + E2-E4): polish, perf, OTP plumbing,
  dictionary wiring.

Update all CLAUDE.md, README.md, and apps/* CLAUDE.md references to
point at the new files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Codify the rule that ARCHITECTURE.md must track the current
high-level shape of the code: schema, supervision tree, worker
contracts, modules, and architectural decisions. Implementation
detail and routine refactors do not warrant updates.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bring ARCHITECTURE.md into compliance with the maintenance directive
just added to CLAUDE.md: high-level shape of the code, not
implementation history.

Key changes:
- Honest §1 status block: kernel functional under single-inheritance,
  with multi-inheritance / templates / multilingual called out as
  open architectural questions.
- Updated terminology throughout: Ontology / Project (instance space)
  per the-knowledge-network.md.
- New §10 "Open Architectural Questions" enumerates the pending
  schema additions (template_nref, kind), multi-inheritance
  representation, template node decision, multilingual storage, and
  the PART-OF dual-storage invariant — each linked to its task in
  TASKS-CRITICAL/HIGH/MEDIUM.md.
- Removed the resolved-historical-questions section, the file-by-file
  implementation log, the implementation-order list (now in
  TASKS-*.md), and the additional-parents-flag debate.
- Trimmed the full 30-node bootstrap table; references bootstrap.terms
  for detail.
- Net reduction: 538 → 365 lines.

Update CLAUDE.md directory listing to drop the "all decisions
resolved" descriptor.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pad table cells so pipes align vertically across all rows, per the
global markdown structural-readability rule. No content changes —
purely whitespace inside table cells.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
the-knowledge-network.md §7 now states the design explicitly:
templates live as compositional children of their class, every class
is born with a `default` template so the first connection works
without ceremony, and class authors force explicit disambiguation by
deleting the default.

TASKS-CRITICAL.md restructured around this shift:
- C1 replaces "add template_nref field" with three subparts —
  bootstrap-seed `Template` AVP attribute (nref 31), auto-attach
  default template in graphdb_class:create_class, enforce template
  AVP presence-by-kind on relationship writes.
- C2 keeps the relationship `kind` field but drops the now-obsolete
  template_nref line; adds template-related "why this matters" bullets.
- C3 (new) adds `template` to the node kind atom set as a fifth peer
  of category/attribute/class/instance.

Execution order called out in the prelude: C2 → C3 → C1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both files previously had dependent tasks numbered before their
prerequisites, forcing a reader to scan past forward references.
Renumbered so file order matches execution order:

  TASKS-CRITICAL: old C2 -> C1, C3 -> C2, C1 -> C3
  TASKS-HIGH:     old H4 -> H1, H5 -> H2, H1 -> H3, H2 -> H4, H3 -> H5

Updated all cross-references in ARCHITECTURE.md and the four task
files. Also corrected two stale `template_nref` field references in
ARCHITECTURE.md left over from the AVP recast.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds an explicit `kind` field to the `-record(relationship, ...)`
schema, with atom values `taxonomy | composition | connection |
instantiation` per `the-knowledge-network.md` §5. Bootstrap loader
reads kind from each tuple in `bootstrap.terms` (Option B — declared
explicitly, not derived from the characterization nref). Worker write
paths assign kind based on arc semantics:

  - attribute/category compositional arcs -> composition
  - class hierarchy arcs (chars 25/26)    -> taxonomy
  - instance compositional arcs (27/28)   -> composition
  - instance<->class membership (29/30)   -> instantiation
  - runtime user arcs via add_relationship -> connection

`graphdb_bootstrap:validate_relationships/1` rejects unknown kinds
during load. All 5 source modules and all 5 CT suites carry the new
record arity. 156 tests still pass (94 CT + 62 EUnit).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extend the legal node kind set from four atoms to five:
category | attribute | class | instance | template.

This task only makes the kind exist; no template nodes are created
yet and no template-specific behaviour is wired (C3 covers the
bootstrap-seeded `Template` AVP, the auto-default-template on class
creation, and the per-kind enforcement of the Template AVP on
Connection arcs).

Touched:
  - graphdb_bootstrap: validate/2 accepts template; kind_order(template)=5;
    sort-priority comment updated
  - graphdb_attr/class/instance/mgr: record kind comment widened
  - CLAUDE.md, ARCHITECTURE.md, apps/graphdb/CLAUDE.md: kind enumeration
    updated. The target_kind description in the relationship-attribute
    docs is intentionally left at the original four — templates are
    semantic scope markers, not arc targets, and valid_target_kind/1
    in graphdb_attr deliberately excludes them.
  - graphdb_bootstrap_tests: validate_template_kind_test,
    kind_order_instance_before_template_test, kind_order_values_test
    extended to cover the new atom

Existing kind-restrictive matches (#node{kind = class},
#node{kind = attribute}, etc.) naturally reject template via pattern
matching and need no change.

158 tests green (94 CT + 64 EUnit, up from 156).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
C3a — Bootstrap-seed the `Template` AVP attribute as nref 31, parented at
Instance Relationships (16). graphdb_attr:init/1 stamps the
`relationship_avp => true` AVP post-bootstrap so the marker resolves
through the same path as other relationship-AVP attributes.

C3b — graphdb_class:create_class/2 atomically writes the class node,
its taxonomy arcs, and a child default template node (kind = template,
name "default") with its compositional arcs. New API:
add_template/2, get_template/1, templates_for_class/1,
default_template/1, class_in_ancestry/2.

C3c — graphdb_instance:add_relationship/4 auto-discovers the source's
class default template; add_relationship/5 accepts an explicit
TemplateNref. Both stamp `#{attribute => 31, value => TemplateNref}` on
each direction of the Connection arc and validate that the template's
parent class is in the taxonomic ancestry of the source or target
class.

Tests: 115 CT + 64 EUnit = 179, all green (was 158). Bootstrap counts
updated (30→31 nodes, 58→60 relationships). TASKS-CRITICAL.md marked
complete per the task-file retirement workflow; the next PR opens with
its removal.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@david-w-t david-w-t merged commit ce2e281 into davidwt-com:main May 7, 2026
1 check passed
david-w-t added a commit to david-w-t/SeerStoneGraphDb that referenced this pull request May 7, 2026
Opens the next series of work. C1, C2, and C3 landed in PR davidwt-com#9
(`ce2e281`); the task file's job is done. Per the task-file retirement
workflow, this commit removes the file and updates every doc that
enumerated it: project root `README.md`, `CLAUDE.md`, `ARCHITECTURE.md`,
plus `apps/database/CLAUDE.md` and `apps/graphdb/CLAUDE.md`. The
remaining task files are now `TASKS-HIGH.md`, `TASKS-MEDIUM.md`, and
`TASKS-LOW.md`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
david-w-t added a commit that referenced this pull request May 8, 2026
* Retire TASKS-CRITICAL.md and clean up doc references

Opens the next series of work. C1, C2, and C3 landed in PR #9
(`ce2e281`); the task file's job is done. Per the task-file retirement
workflow, this commit removes the file and updates every doc that
enumerated it: project root `README.md`, `CLAUDE.md`, `ARCHITECTURE.md`,
plus `apps/database/CLAUDE.md` and `apps/graphdb/CLAUDE.md`. The
remaining task files are now `TASKS-HIGH.md`, `TASKS-MEDIUM.md`, and
`TASKS-LOW.md`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* H1+H2: walk class taxonomy on lookup; restrict P4 to connection arcs

H1 (graphdb_instance:resolve_from_class)
  Stop reading exactly one class node's AVPs.  Locate the membership
  arc via the existing do_class_of/1, then ask graphdb_class for the
  class node and ancestor chain and return the first AVP match.
  Subsumes M2 (resolve_from_class no longer reads the nodes table
  directly or hard-codes ?CLASS_MEMBERSHIP_ARC inside the resolver).

H2 (graphdb_instance:resolve_from_connected)
  Filter the outgoing relationships to kind = connection before
  pulling target nrefs.  Instantiation (membership, char=29) and
  composition (parent/child, char=27/28) arcs no longer feed
  Priority 4; those targets are already covered by Priorities 2 and 3.

Tests
  Three new CT cases in graphdb_instance_SUITE:
    - resolve_value_walks_class_taxonomy
    - resolve_value_local_class_overrides_taxonomy_ancestor
    - resolve_value_p4_ignores_compositional_arc
  Full suite: 118 CT + 64 EUnit = 182, all green.

Docs
  TASKS-HIGH.md: H1 and H2 marked RESOLVED with status notes; intro
  rewritten to reflect that only H3-H5 remain.
  TASKS-MEDIUM.md: M2 marked RESOLVED (closed by H1).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* H0a: charter the "arcs authoritative; hierarchy lists cached" invariant

Adds the H0 decision record (arcs-authoritative.md) and an H0 entry
to TASKS-HIGH.md with substep checklist (H0a-H0e).  No code changes.

Decision in summary:
  - Arcs are the sole authoritative source for hierarchy (taxonomy,
    composition, instantiation).
  - node.parents :: [integer()] and node.classes :: [integer()] are
    caches reconstructable from the arcs.  node.parent (singular) is
    retired.
  - Each cache field has exactly one owner worker; arc and cache
    updates happen in one mnesia:transaction/1.
  - Bootstrap follows Option B: arcs only in the file, with %%
    comments per relationship; loader rebuilds and verifies caches
    after writing arcs.
  - Cache/arc disagreement is a fatal error.

H0 lands before H3 so the multi-parent class case (H3) and
multi-class instance case (H4) build on a single uniform pattern
rather than schema migrations tangled with semantic changes.
H0 closes M1 ("PART-OF stored in two places with no consistency
invariant") on completion.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* H0b: replace node.parent with parents/classes cache lists

Schema change for the "arcs authoritative; hierarchy lists cached"
invariant (charter: arcs-authoritative.md, plan: TASKS-HIGH.md H0b).

Record change in `node`:
  - retire `parent :: integer() | undefined`
  - add `parents = [] :: [integer()]` -- cache of compositional /
    taxonomic parent arcs
  - add `classes = [] :: [integer()]` -- cache of instantiation arcs
    (instances only)

Bootstrap loader (graphdb_bootstrap):
  - term_to_node converts the legacy single Parent integer into
    parents=[Parent] (or [] for the Root node) and seeds classes=[]
  - drop {index, [parent]} from create_tables; downward lookups now
    go through the relationships table
  - bootstrap.terms format unchanged (Option B switch lands in H0d)

Write paths populate caches transactionally:
  - graphdb_attr:do_create_attribute / do_create_seed_attribute
  - graphdb_class:do_create_class (class + default template),
    do_write_template, do_create_seed_attribute
  - graphdb_instance:do_write_instance (parents + classes)

Read paths replace the retired parent index:
  - downward "list children" lookups switch to a private
    downward_children_by_arc/3 helper that reads outgoing arcs from
    the relationships table filtered by Kind + characterization
  - graphdb_attr: find_attribute_by_name, do_list_children (char=24)
  - graphdb_class: find_attribute_by_name, do_find_template_by_name,
    do_templates_for_class (char=26 composition), do_subclasses
    (char=26 taxonomy)
  - graphdb_instance: do_children (char=28 composition)

Single-chain ancestor walks read parents=[P|_] via head_parent/1
helper; multi-parent traversal arrives in H3.  validate_template_scope
and resolve_from_ancestors switch to the same helper.

Tests: 64 EUnit + 118 CT = 182 all green.  Caches populated as
length-1 lists; single-parent semantics preserved per H0b spec.
graphdb_bootstrap_SUITE:load_category_children rewritten to verify
children via composition arcs (the parent index is gone).
graphdb_bootstrap_tests element/_ position assertions updated for
the new {node, Nref, Kind, Parents, Classes, AVPs} tuple shape.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* H0c: graphdb_mgr verify_caches/0 + rebuild_caches/0; CT enforcement

Adds the cache-invariant audit/repair APIs spec'd in
arcs-authoritative.md and wires them into every CT suite.

graphdb_mgr exports two new APIs:
  - verify_caches/0 -> ok | {error, [{Nref, Field, Expected, Actual}]}
    Scans every node, compares parents/classes against the arcs.
    Order-insensitive; returns the full mismatch list when wrong.
  - rebuild_caches/0 -> ok | {error, term()}
    Rewrites every node's parents/classes from the arcs in one txn.
    Used as a repair tool and (after H0d) as the bootstrap loader's
    post-load tail.

Internal helpers:
  - expected_parents/1 reads outgoing arcs (kind in {composition,
    taxonomy}) whose characterization is one of the parent labels
    {21, 23, 25, 27} and returns the target nrefs.
  - expected_classes/1 reads outgoing instantiation arcs (char=29)
    and returns the target class nrefs (empty for non-instances).
  - verify_one/1 / rebuild_one/1 -- per-node primitives.

CT enforcement -- every suite's end_per_testcase now calls a local
verify_cache_invariant/1 helper that asserts verify_caches/0 returns
ok before teardown.  A failed verify is a fatal CT failure with
ct:pal'd Mismatches.  All 118 pre-existing testcases still pass with
the wiring in place: the H0b write paths populate caches correctly.

New direct CT coverage (graphdb_mgr_SUITE cache_audit group, +4):
  - verify_caches_clean_after_bootstrap
  - verify_caches_detects_poisoned_parents
    (poison node 6's parents -> [9999], expect mismatch tuple)
  - verify_caches_detects_poisoned_classes
    (poison node 7's classes -> [42], expect mismatch tuple)
  - rebuild_caches_restores_after_poison
    (3 caches poisoned, rebuild, then verify ok)

Tests: 122 CT (+4) + 64 EUnit = 186 all green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* H0d: bootstrap.terms to Option B; loader rebuilds + verifies caches

Arcs become the sole authoritative source of hierarchy in the
bootstrap file.  Node tuples no longer carry a Parent integer; the
existing inline %% arc comments make the file human-followable
top-to-bottom.

apps/graphdb/priv/bootstrap.terms:
  Old: {node, Nref, Kind, Parent, {NameAttr, Name}, AVPs}
  New: {node, Nref, Kind, {NameAttr, Name}, AVPs}
  All 31 node tuples converted; 30 relationship terms unchanged;
  documentation comments updated to describe the new shape.

graphdb_bootstrap.erl:
  - classify_terms/4, sort_nodes_by_kind/1, validate/2 match the
    5-tuple form.
  - term_to_node/1 sets parents=[], classes=[] (caches are filled
    by rebuild_caches/0 once all arcs are written).
  - do_load/0 calls rebuild_and_verify_caches/0 after writing all
    nodes and arcs.  rebuild_and_verify_caches/0 invokes
    graphdb_mgr:rebuild_caches/0 then graphdb_mgr:verify_caches/0;
    a verify mismatch throws {bootstrap_cache_invariant_failed,
    Mismatches} as a fatal startup error.

graphdb_bootstrap_tests:
  - All 6-tuple node terms in classify_terms/sort/validate/
    term_to_node tests rewritten to 5-tuples.
  - List-comprehension matchers updated from {node,_,K,_,_,_} to
    {node,_,K,_,_}.
  - term_to_node tests now expect parents=[] (the rebuild step
    happens at load/0 level, outside term_to_node's contract).

graphdb_bootstrap_SUITE:
  - Two error-path tests (load_missing_nref_start,
    load_nref_above_floor) updated to write the new tuple shape.

Tests: 122 CT + 64 EUnit = 186 all green.  graphdb_bootstrap_SUITE
load tests still see correct parents/classes caches because the
new rebuild step populates them; the existing
load_root_node_correct, load_attribute_node_correct,
load_template_avp_node_correct, and load_category_children
testcases all continue to pass with the same expected values.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* H0e: fold cache invariant into ARCHITECTURE.md; mark H0+M1 RESOLVED

Closes the H0 series.  The "arcs authoritative; hierarchy lists
cached" invariant is now a first-class architectural property of
the kernel, summarised in ARCHITECTURE.md and enforced by
graphdb_mgr:verify_caches/0 at every CT testcase boundary and the
bootstrap loader's tail.

ARCHITECTURE.md updates:
  - Status table: 186 tests (was 156); graphdb_mgr line names cache
    audit/repair as a feature.
  - §2 Storage indexes: drop the retired nodes parent index; document
    the arc-based downward-query path.
  - §3 Node Record: new record schema (parents/classes lists);
    new "Cache invariant" subsection covering the three rules,
    cache-field source table, single-writer ownership, and the
    verify_caches/0 / rebuild_caches/0 audit APIs.  Adds template
    to the node-kinds table.
  - §8 Bootstrap: 5-tuple node format documented; loader description
    notes the rebuild + verify pass and the
    bootstrap_cache_invariant_failed startup error.
  - §9 Inheritance: Priority 3 walks node.parents (single-chain today,
    DAG via H3); H1+H2 dropped from "known correctness gaps" since
    they landed in a078373.
  - §10 Open Questions: "Composition: dual storage" removed (resolved
    by H0); multi-inheritance entry rephrased to reflect that the
    cache-list infrastructure already landed.

arcs-authoritative.md: status flipped to Accepted with the H0a-H0e
commit chain; "Future work" notes the doc fold.

TASKS-HIGH.md: H0 marked RESOLVED with a commit-by-commit summary.
The header preamble now reflects that H0 has landed (was: "in
flight"); H3-H5 framed as additive work atop the cache
infrastructure rather than tangled with schema migration.

TASKS-MEDIUM.md: M1 marked RESOLVED, pointing at H0 + the
arcs-authoritative.md / ARCHITECTURE.md §3 references.

CLAUDE.md (root + apps/graphdb): node record schema updated;
apps/graphdb/CLAUDE.md describes the cache-invariant + audit APIs in
place of the retired parent index.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant