causalontology 2.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +56 -14
  3. data/conformance.rb +503 -11
  4. data/lib/causalontology/canonical.rb +14 -4
  5. data/lib/causalontology/schema.rb +14 -1
  6. data/lib/causalontology/semantics.rb +161 -16
  7. data/lib/causalontology/spec/schema/assertion.schema.json +75 -0
  8. data/lib/causalontology/spec/schema/attitude.schema.json +45 -0
  9. data/lib/causalontology/spec/schema/bridge.schema.json +46 -0
  10. data/lib/causalontology/spec/schema/causal_relation_object.schema.json +111 -0
  11. data/lib/causalontology/spec/schema/conduit.schema.json +56 -0
  12. data/lib/causalontology/spec/schema/continuant.schema.json +38 -0
  13. data/lib/causalontology/spec/schema/cross_stratal_seam.schema.json +50 -0
  14. data/lib/causalontology/spec/schema/enrichment.schema.json +80 -0
  15. data/lib/causalontology/spec/schema/individual.schema.json +36 -0
  16. data/lib/causalontology/spec/schema/occurrent.schema.json +42 -0
  17. data/lib/causalontology/spec/schema/port.schema.json +56 -0
  18. data/lib/causalontology/spec/schema/predicted_occurrence.schema.json +68 -0
  19. data/lib/causalontology/spec/schema/prediction_error.schema.json +37 -0
  20. data/lib/causalontology/spec/schema/quality.schema.json +44 -0
  21. data/lib/causalontology/spec/schema/realizable.schema.json +38 -0
  22. data/lib/causalontology/spec/schema/retraction.schema.json +43 -0
  23. data/lib/causalontology/spec/schema/state.schema.json +89 -0
  24. data/lib/causalontology/spec/schema/stratum.schema.json +52 -0
  25. data/lib/causalontology/spec/schema/succession.schema.json +39 -0
  26. data/lib/causalontology/spec/schema/token.schema.json +96 -0
  27. data/lib/causalontology/spec/schema/token_causal_claim.schema.json +76 -0
  28. data/lib/causalontology/store.rb +5 -2
  29. data/lib/causalontology.rb +17 -1
  30. metadata +23 -2
@@ -14,9 +14,13 @@ require_relative "jcs"
14
14
 
15
15
  module Causalontology
16
16
  module Canonical
17
- # The identity-bearing fields of each of the seventeen kinds. "type" is
18
- # always injected, so it is not listed here. Order does not matter (JCS
19
- # sorts keys).
17
+ # The identity-bearing fields of each of the twenty-one kinds (3.0.0 adds the
18
+ # cross_stratal_seam; the conduit gains realized_by; 4.0.0 adds the attitude,
19
+ # the predicted_occurrence, and the prediction_error - all additive and
20
+ # identity-preserving - a record that omits a new field keeps its earlier
21
+ # identifier byte-for-byte, and the new kinds open new identity schemes that
22
+ # disturb no existing record). "type" is always injected, so it is not listed
23
+ # here. Order does not matter (JCS sorts keys).
20
24
  IDENTITY_FIELDS = {
21
25
  # ---- type tier ----
22
26
  "occurrent" => ["label", "category", "stratum"],
@@ -26,8 +30,10 @@ module Causalontology
26
30
  "realizable" => ["kind", "bearer", "label"],
27
31
  "stratum" => ["label", "scheme", "ordinal", "unit", "governs"],
28
32
  "bridge" => ["coarse", "fine", "relation"],
33
+ "cross_stratal_seam" => ["source", "target", "mechanism_status", "chain"],
29
34
  "port" => ["bearer", "label", "direction", "accepts", "realizable"],
30
- "conduit" => ["label", "from", "to", "carries", "transform"],
35
+ "conduit" => ["label", "from", "to", "carries", "transform",
36
+ "realized_by"],
31
37
  "quality" => ["label", "datatype", "unit", "stratum"],
32
38
  # ---- token tier ----
33
39
  "token_individual" => ["instantiates", "designator", "part_of"],
@@ -36,6 +42,10 @@ module Causalontology
36
42
  "state_assertion" => ["subject", "quality", "value", "interval"],
37
43
  "token_causal_claim" => ["causes", "effects", "covering_law",
38
44
  "actual_delay", "counterfactual"],
45
+ "attitude" => ["holder", "attitude_type", "content"],
46
+ "predicted_occurrence" => ["instantiates", "interval", "predictor",
47
+ "strength"],
48
+ "prediction_error" => ["predicted", "observed", "discrepancy"],
39
49
  # ---- provenance tier ----
40
50
  "assertion" => ["about", "source", "evidence_type", "evidence", "strength",
41
51
  "confidence", "timestamp", "evidenced_by"],
@@ -3,7 +3,7 @@
3
3
  # Schema validation against spec/schema/*.schema.json.
4
4
  #
5
5
  # A deliberately small interpreter for exactly the JSON Schema keywords the
6
- # seventeen Causalontology schemas use: type, const, enum, pattern, required,
6
+ # twenty-one Causalontology schemas use: type, const, enum, pattern, required,
7
7
  # properties, additionalProperties, items, minItems, minLength, minimum,
8
8
  # maximum, oneOf, local $ref (#/$defs/...), and cross-file $ref to a sibling
9
9
  # schema (https://causalontology.org/schema/<file>.schema.json#/...). "format"
@@ -23,6 +23,7 @@ module Causalontology
23
23
  "realizable" => "realizable.schema.json",
24
24
  "stratum" => "stratum.schema.json",
25
25
  "bridge" => "bridge.schema.json",
26
+ "cross_stratal_seam" => "cross_stratal_seam.schema.json",
26
27
  "port" => "port.schema.json",
27
28
  "conduit" => "conduit.schema.json",
28
29
  "quality" => "quality.schema.json",
@@ -30,6 +31,9 @@ module Causalontology
30
31
  "token_occurrence" => "token.schema.json",
31
32
  "state_assertion" => "state.schema.json",
32
33
  "token_causal_claim" => "token_causal_claim.schema.json",
34
+ "attitude" => "attitude.schema.json",
35
+ "predicted_occurrence" => "predicted_occurrence.schema.json",
36
+ "prediction_error" => "prediction_error.schema.json",
33
37
  "assertion" => "assertion.schema.json",
34
38
  "enrichment" => "enrichment.schema.json",
35
39
  "retraction" => "retraction.schema.json",
@@ -41,9 +45,18 @@ module Causalontology
41
45
  @cache = {}
42
46
 
43
47
  class << self
48
+ # Where the twenty-one *.schema.json files live, in strict precedence:
49
+ #
50
+ # (a) $CAUSALONTOLOGY_SPEC/schema - explicit override, always wins;
51
+ # (b) the copy vendored inside the gem - what an installed consumer
52
+ # uses, so validation works standalone with no repository present;
53
+ # (c) the repository-relative path - last resort, for working directly
54
+ # in a checkout where (b) has not been vendored yet.
44
55
  def schema_dir
45
56
  env = ENV["CAUSALONTOLOGY_SPEC"]
46
57
  return File.join(env, "schema") if env && !env.empty?
58
+ bundled = File.expand_path("spec/schema", __dir__)
59
+ return bundled if File.directory?(bundled)
47
60
  # lib/causalontology -> lib -> ruby -> bindings -> repository root
48
61
  File.expand_path("../../../../spec/schema", __dir__)
49
62
  end
@@ -22,6 +22,13 @@ module Causalontology
22
22
  "years" => 31556952,
23
23
  }.freeze
24
24
 
25
+ # 3.0.0: the ordinal (dimensionless) temporal units. A tick is a discrete
26
+ # step with NO wall-clock mapping; a tick window is ordered by integer
27
+ # comparison, and an ordinal window and a wall-clock window are DIFFERENT
28
+ # DIMENSIONS that do not compare (mixing them is never within-window and
29
+ # never overlapping).
30
+ ORDINAL_UNITS = Set.new(["ticks"]).freeze
31
+
25
32
  # Rule 12: enrichment field-to-kind validity and entry shapes. Two
26
33
  # occurrent forms added in 2.0.0.
27
34
  ENRICHMENT_FIELDS = {
@@ -47,6 +54,19 @@ module Causalontology
47
54
  Canonical::KIND_OF_PREFIX[identifier.split(":", 2)[0]]
48
55
  end
49
56
 
57
+ # 3.0.0: "ordinal" for a tick-like unit, else "wallclock".
58
+ def dimension(unit)
59
+ ORDINAL_UNITS.include?(unit) ? "ordinal" : "wallclock"
60
+ end
61
+
62
+ # 3.0.0: a comparable magnitude within ONE dimension: raw tick count for an
63
+ # ordinal unit, seconds for a wall-clock unit. Never mix dimensions.
64
+ def magnitude(value, unit)
65
+ return value if ORDINAL_UNITS.include?(unit) # a dimensionless tick count
66
+ return 0 if unit == "instant"
67
+ value * UNIT_SECONDS.fetch(unit)
68
+ end
69
+
50
70
  # [ok, reasons] - the locally checkable semantic rules.
51
71
  def validate_semantics(obj, kind = nil)
52
72
  kind ||= Canonical.infer_kind(obj)
@@ -96,6 +116,41 @@ module Causalontology
96
116
  end
97
117
  end
98
118
 
119
+ # 3.0.0 Rule 22, local clause: a Cross Stratal Seam that DRAWS a chain has,
120
+ # by drawing it, a modelled intervening mechanism - so mechanism_status
121
+ # 'absent' contradicts a present chain (the honest-ignorance distinction
122
+ # must stay honest). The stratal well-formedness (non-adjacency, adjacency
123
+ # of chain steps, scheme, the home rule) needs the strata map and lives in
124
+ # seam_wellformed, exactly as bridge well-formedness does.
125
+ if kind == "cross_stratal_seam"
126
+ if !obj["chain"].nil? && obj["mechanism_status"] == "absent"
127
+ errors << "contradictory_seam: a drawn chain cannot carry " \
128
+ "mechanism_status 'absent' (a drawn mechanism is not absent)"
129
+ end
130
+ end
131
+
132
+ # 4.0.0 Rule 24, local clause: a predicted_occurrence's interval carries
133
+ # exactly ONE temporal dimension - a wall-clock start (optional end) or an
134
+ # ordinal start_tick (optional end_tick), never both and never neither.
135
+ # Per Rule 23 the two dimensions never compare. The pairing check of a
136
+ # prediction_error against its predicted_occurrence and its observed
137
+ # token_occurrence needs those objects and lives in
138
+ # prediction_pairing_mismatch, exactly as covering_law_mismatch does.
139
+ if kind == "predicted_occurrence"
140
+ iv = obj["interval"] || {}
141
+ wall = iv.key?("start")
142
+ tick = iv.key?("start_tick")
143
+ if wall && tick
144
+ errors << "dimension_conflict: a predicted interval must " \
145
+ "carry exactly one temporal dimension, not a " \
146
+ "wall-clock start AND an ordinal start_tick"
147
+ end
148
+ if !wall && !tick
149
+ errors << "missing_dimension: a predicted interval must " \
150
+ "carry a wall-clock start or an ordinal start_tick"
151
+ end
152
+ end
153
+
99
154
  [errors.empty?, errors]
100
155
  end
101
156
 
@@ -105,26 +160,27 @@ module Causalontology
105
160
  [!missing.empty?, missing]
106
161
  end
107
162
 
108
- # Rule 4: temporal admissibility with the fixed constants.
109
- def admissible(cro, elapsed_seconds)
163
+ # Rule 4: temporal admissibility. For a wall-clock window `elapsed` is in
164
+ # seconds; for an ordinal ('ticks') window `elapsed` is a tick count.
165
+ # Ordering is by magnitude WITHIN the window's own dimension (3.0.0).
166
+ def admissible(cro, elapsed)
110
167
  t = cro["temporal"]
111
168
  return true if t.nil? # no window imposes no constraint
112
- unit = UNIT_SECONDS.fetch(t["unit"])
113
- lo = t["minimum_delay"] * unit
114
- hi = t["maximum_delay"] * unit
115
- lo <= elapsed_seconds && elapsed_seconds <= hi
169
+ lo = magnitude(t["minimum_delay"], t["unit"])
170
+ hi = magnitude(t["maximum_delay"], t["unit"])
171
+ lo <= elapsed && elapsed <= hi
116
172
  end
117
173
 
118
174
  def window_overlap(a, b)
119
175
  ta = a["temporal"]
120
176
  tb = b["temporal"]
121
177
  return true if ta.nil? || tb.nil? # either absent counts as overlapping
122
- ua = UNIT_SECONDS.fetch(ta["unit"])
123
- ub = UNIT_SECONDS.fetch(tb["unit"])
124
- lo_a = ta["minimum_delay"] * ua
125
- hi_a = ta["maximum_delay"] * ua
126
- lo_b = tb["minimum_delay"] * ub
127
- hi_b = tb["maximum_delay"] * ub
178
+ # 3.0.0: an ordinal window and a wall-clock window never overlap
179
+ return false if dimension(ta["unit"]) != dimension(tb["unit"])
180
+ lo_a = magnitude(ta["minimum_delay"], ta["unit"])
181
+ hi_a = magnitude(ta["maximum_delay"], ta["unit"])
182
+ lo_b = magnitude(tb["minimum_delay"], tb["unit"])
183
+ hi_b = magnitude(tb["maximum_delay"], tb["unit"])
128
184
  lo_a <= hi_b && lo_b <= hi_a
129
185
  end
130
186
 
@@ -309,19 +365,31 @@ module Causalontology
309
365
  end
310
366
 
311
367
  # ALGORITHM E helper: normalize a delay to seconds by the fixed table.
368
+ # 3.0.0: an ordinal ('ticks') unit is dimensionless and has NO wall-clock
369
+ # mapping - converting one to seconds is a category error and is refused.
312
370
  def to_seconds(duration, unit)
371
+ if ORDINAL_UNITS.include?(unit)
372
+ raise ArgumentError,
373
+ "'#{unit}' is an ordinal (dimensionless) unit and has no " \
374
+ "wall-clock seconds mapping"
375
+ end
313
376
  return 0 if unit == "instant"
314
377
  duration * UNIT_SECONDS.fetch(unit)
315
378
  end
316
379
 
317
380
  # ALGORITHM E (Rule 20): does an observed delay fall within a covering
318
- # law's temporal window? Inclusive at both ends (N12.5.2).
381
+ # law's temporal window? Inclusive at both ends (N12.5.2). 3.0.0: an ordinal
382
+ # delay compares to an ordinal window by integer tick count; an ordinal
383
+ # delay and a wall-clock window (or vice versa) are different dimensions and
384
+ # never fall within one another.
319
385
  def delay_within_window(actual_delay, temporal)
320
386
  return true if actual_delay.nil? || actual_delay.empty? ||
321
387
  temporal.nil? || temporal.empty?
322
- observed = to_seconds(actual_delay["duration"], actual_delay["unit"])
323
- lo = to_seconds(temporal["minimum_delay"], temporal["unit"])
324
- hi = to_seconds(temporal["maximum_delay"], temporal["unit"])
388
+ # dimension mismatch: a tick delay is not within a wall-clock window
389
+ return false if dimension(actual_delay["unit"]) != dimension(temporal["unit"])
390
+ observed = magnitude(actual_delay["duration"], actual_delay["unit"])
391
+ lo = magnitude(temporal["minimum_delay"], temporal["unit"])
392
+ hi = magnitude(temporal["maximum_delay"], temporal["unit"])
325
393
  lo <= observed && observed <= hi
326
394
  end
327
395
 
@@ -348,6 +416,73 @@ module Causalontology
348
416
  [true, "well-formed bridge"]
349
417
  end
350
418
 
419
+ # 3.0.0 Rule 22 / Algorithm F: Cross Stratal Seam well-formedness.
420
+ # [ok, reason]. All of (a)-(g) must hold, else malformed_seam. A seam is a
421
+ # MANAGED jump across NON-ADJACENT strata; when it DRAWS a chain, the chain
422
+ # must be an adjacent-stratum path spanning the two endpoints' strata.
423
+ def seam_wellformed(seam, occ_map, stratum_map)
424
+ src_s = (occ_map[seam["source"]] || {})["stratum"]
425
+ tgt_s = (occ_map[seam["target"]] || {})["stratum"]
426
+ if src_s.nil? || tgt_s.nil?
427
+ return [false, "malformed_seam: an endpoint has no stratum (a)"]
428
+ end
429
+ if stratum_map[src_s]["scheme"] != stratum_map[tgt_s]["scheme"]
430
+ return [false, "malformed_seam: endpoints differ in scheme (b)"]
431
+ end
432
+ so = stratum_map[src_s]["ordinal"]
433
+ to_ = stratum_map[tgt_s]["ordinal"]
434
+ if (so - to_).abs <= 1
435
+ return [false, "malformed_seam: endpoints are adjacent or co-stratal; " \
436
+ "a seam is for NON-adjacent strata (c)"]
437
+ end
438
+ chain = seam["chain"]
439
+ unless chain.nil?
440
+ if seam["mechanism_status"] == "absent"
441
+ return [false, "malformed_seam: a drawn chain contradicts " \
442
+ "mechanism_status 'absent' (d)"]
443
+ end
444
+ lo = [so, to_].min
445
+ hi = [so, to_].max
446
+ ords = []
447
+ chain.each do |oid|
448
+ st = (occ_map[oid] || {})["stratum"]
449
+ if st.nil?
450
+ return [false, "malformed_seam: a chain member has no stratum (e)"]
451
+ end
452
+ if stratum_map[st]["scheme"] != stratum_map[src_s]["scheme"]
453
+ return [false, "malformed_seam: a chain member differs in scheme (e)"]
454
+ end
455
+ ords << stratum_map[st]["ordinal"]
456
+ end
457
+ unless ords.all? { |o| lo < o && o < hi }
458
+ return [false, "malformed_seam: a chain member is not at an " \
459
+ "INTERVENING stratum, strictly between the endpoints (f)"]
460
+ end
461
+ diffs = (0...(ords.length - 1)).map { |i| ords[i + 1] - ords[i] }
462
+ if !diffs.empty? &&
463
+ !(diffs.all? { |d| d > 0 } || diffs.all? { |d| d < 0 })
464
+ return [false, "malformed_seam: chain is not strictly monotone from " \
465
+ "one endpoint toward the other (g)"]
466
+ end
467
+ end
468
+ [true, "well-formed cross_stratal_seam"]
469
+ end
470
+
471
+ # THE HOME RULE (3.0.0): a Cross Stratal Seam belongs to the COARSEST stratum
472
+ # it touches - the endpoint of the greater ordinal. Returns that stratum's
473
+ # identifier (nil if an endpoint is unstratified). A layer-to-stratum binding
474
+ # places and checks the seam by this rule.
475
+ def seam_home(seam, occ_map, stratum_map)
476
+ src_s = (occ_map[seam["source"]] || {})["stratum"]
477
+ tgt_s = (occ_map[seam["target"]] || {})["stratum"]
478
+ return nil if src_s.nil? || tgt_s.nil?
479
+ if stratum_map[src_s]["ordinal"] >= stratum_map[tgt_s]["ordinal"]
480
+ src_s
481
+ else
482
+ tgt_s
483
+ end
484
+ end
485
+
351
486
  # Rule 17 / N4.2.1-2: Conduit well-formedness. [ok, reason]. N4.2.1 with
352
487
  # the transform exception of N4.2.2.
353
488
  def conduit_wellformed(conduit, port_map, cro_map = nil)
@@ -417,6 +552,16 @@ module Causalontology
417
552
  false
418
553
  end
419
554
 
555
+ # 4.0.0 Rule 24: prediction-to-observation pairing. True iff the prediction
556
+ # error's observed token does not instantiate the occurrent its
557
+ # predicted_occurrence instantiates (surfaces pairing_mismatch). An ABSENT
558
+ # observed is never a mismatch - it means the predicted occurrence was not
559
+ # fulfilled by any recorded occurrence.
560
+ def prediction_pairing_mismatch(error, predicted, observed)
561
+ return false if error["observed"].nil? || observed.nil?
562
+ observed["instantiates"] != predicted["instantiates"]
563
+ end
564
+
420
565
  # Rule 21: true iff any cause token starts after any effect token (HARD;
421
566
  # retrocausal_claim). RFC 3339 UTC "Z" strings compare lexicographically.
422
567
  def retrocausal(tcc, token_map)
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://causalontology.org/schema/assertion.schema.json",
4
+ "title": "Assertion",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "about",
9
+ "source",
10
+ "evidence_type",
11
+ "confidence",
12
+ "timestamp"
13
+ ],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "id": {
17
+ "type": "string",
18
+ "pattern": "^assertion:[0-9a-f]{64}$"
19
+ },
20
+ "type": {
21
+ "const": "assertion"
22
+ },
23
+ "about": {
24
+ "type": "string",
25
+ "pattern": "^(causal_relation_object|occurrent|continuant|realizable|stratum|bridge|cross_stratal_seam|port|conduit|quality|token_individual|token_occurrence|state_assertion|token_causal_claim|attitude|predicted_occurrence|prediction_error):[0-9a-f]{64}$",
26
+ "description": "the content object this assertion is about (widened in 2.0.0 to the nine new content kinds; widened in 4.0.0 to attitude, predicted_occurrence, and prediction_error, and to the cross_stratal_seam, whose absence here was a 3.0.0 drift repaired in this major version); about a non-causal object it means the source vouches for the vocabulary item"
27
+ },
28
+ "source": {
29
+ "type": "string",
30
+ "pattern": "^ed25519:[0-9a-f]{64}$"
31
+ },
32
+ "evidence_type": {
33
+ "enum": [
34
+ "intervention",
35
+ "observation",
36
+ "simulation",
37
+ "derivation",
38
+ "human_hint",
39
+ "imported"
40
+ ],
41
+ "description": "how the source came to the claim; ordering from strongest to weakest is intervention, observation, simulation, derivation, human_hint, imported (2.0.0 6.2)"
42
+ },
43
+ "evidence": {
44
+ "type": "string"
45
+ },
46
+ "strength": {
47
+ "type": "number",
48
+ "minimum": 0,
49
+ "maximum": 1,
50
+ "description": "the source's estimate of causal strength (semantics.md rule 5); meaningful only when about references a Causal Relation Object"
51
+ },
52
+ "confidence": {
53
+ "type": "number",
54
+ "minimum": 0,
55
+ "maximum": 1
56
+ },
57
+ "timestamp": {
58
+ "type": "string",
59
+ "format": "date-time"
60
+ },
61
+ "evidenced_by": {
62
+ "type": "array",
63
+ "items": {
64
+ "type": "string",
65
+ "pattern": "^(token_occurrence|token_causal_claim|state_assertion):[0-9a-f]{64}$"
66
+ },
67
+ "description": "the PARTICULAR token records that are the evidence for this claim (2.0.0 6.2). IDENTITY-BEARING."
68
+ },
69
+ "signature": {
70
+ "type": "string",
71
+ "pattern": "^[0-9a-f]{128}$",
72
+ "description": "Ed25519 signature over the record's canonical identity-bearing bytes; excluded from the identity hash"
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://causalontology.org/schema/attitude.schema.json",
4
+ "title": "Attitude",
5
+ "description": "4.0.0. A first-class record of a PROPOSITIONAL ATTITUDE: what a holder's mind CONTAINS, never what is true. The holder is a MODELED agent inside the ontology (a continuant type or a particular token individual), never a cryptographic key; the content is a reference by identity to ANY content object - which may be FALSE, and may itself be another attitude (nesting). An attitude is NOT an assertion and carries no strength (Principle P4): it is asserted, graded, and retracted through the ordinary provenance layer, and the SOURCE that signs an assertion ABOUT an attitude is a different thing from the HOLDER of the attitude (Rule 25).",
6
+ "type": "object",
7
+ "required": [
8
+ "id",
9
+ "type",
10
+ "holder",
11
+ "attitude_type",
12
+ "content"
13
+ ],
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "id": {
17
+ "type": "string",
18
+ "pattern": "^attitude:[0-9a-f]{64}$"
19
+ },
20
+ "type": {
21
+ "const": "attitude"
22
+ },
23
+ "holder": {
24
+ "type": "string",
25
+ "pattern": "^(continuant|token_individual):[0-9a-f]{64}$",
26
+ "description": "the agent whose mind contains the content: a MODELED agent inside the ontology (a continuant type or a particular token individual), never a cryptographic key - the signer of an assertion about this attitude is a SOURCE, and the two are different things (Rule 25)"
27
+ },
28
+ "attitude_type": {
29
+ "enum": [
30
+ "believes",
31
+ "desires",
32
+ "intends",
33
+ "knows",
34
+ "expects",
35
+ "fears"
36
+ ],
37
+ "description": "CLOSED enumeration; extending it is a MAJOR change (Locked Decision 24)"
38
+ },
39
+ "content": {
40
+ "type": "string",
41
+ "pattern": "^(occurrent|causal_relation_object|continuant|realizable|stratum|bridge|cross_stratal_seam|port|conduit|quality|token_individual|token_occurrence|state_assertion|token_causal_claim|attitude|predicted_occurrence|prediction_error):[0-9a-f]{64}$",
42
+ "description": "a reference by identity to ANY content object, INCLUDING another attitude (nesting: A believes that B believes X). The content records what the holder's mind contains, not what is true - it may be FALSE, and a content that contradicts the actual record raises NO conflict (Rule 25: that mismatch IS a false belief, first-class and shareable)"
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://causalontology.org/schema/bridge.schema.json",
4
+ "title": "Bridge",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "type",
9
+ "coarse",
10
+ "fine",
11
+ "relation"
12
+ ],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "id": {
16
+ "type": "string",
17
+ "pattern": "^bridge:[0-9a-f]{64}$"
18
+ },
19
+ "type": {
20
+ "const": "bridge"
21
+ },
22
+ "coarse": {
23
+ "type": "string",
24
+ "pattern": "^occurrent:[0-9a-f]{64}$",
25
+ "description": "the occurrent at the coarser stratum"
26
+ },
27
+ "fine": {
28
+ "type": "array",
29
+ "minItems": 1,
30
+ "items": {
31
+ "type": "string",
32
+ "pattern": "^occurrent:[0-9a-f]{64}$"
33
+ },
34
+ "description": "the occurrents at the finer stratum that jointly constitute, aggregate to, realize, or subvene the coarse one"
35
+ },
36
+ "relation": {
37
+ "enum": [
38
+ "constitutes",
39
+ "aggregates",
40
+ "realizes",
41
+ "supervenes_on"
42
+ ],
43
+ "description": "the cross-stratal relation asserted; CLOSED enumeration"
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://causalontology.org/schema/causal_relation_object.schema.json",
4
+ "title": "Causal Relation Object",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "causes",
9
+ "effects"
10
+ ],
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "id": {
14
+ "$ref": "#/$defs/croId"
15
+ },
16
+ "type": {
17
+ "const": "causal_relation_object"
18
+ },
19
+ "causes": {
20
+ "type": "array",
21
+ "minItems": 1,
22
+ "items": {
23
+ "$ref": "#/$defs/occId"
24
+ }
25
+ },
26
+ "effects": {
27
+ "type": "array",
28
+ "minItems": 1,
29
+ "items": {
30
+ "$ref": "#/$defs/occId"
31
+ }
32
+ },
33
+ "mechanism": {
34
+ "type": "array",
35
+ "items": {
36
+ "$ref": "#/$defs/croId"
37
+ },
38
+ "description": "identifiers of finer Causal Relation Objects whose composition realizes this one (hierarchical decomposition; must be acyclic; consistency per semantics.md rule 7, amended to BRIDGED reachability in 2.0.0)"
39
+ },
40
+ "temporal": {
41
+ "$ref": "#/$defs/temporalWindow"
42
+ },
43
+ "modality": {
44
+ "enum": [
45
+ "necessary",
46
+ "sufficient",
47
+ "contributory",
48
+ "preventive",
49
+ "enabling"
50
+ ]
51
+ },
52
+ "context": {
53
+ "type": "array",
54
+ "items": {
55
+ "$ref": "#/$defs/occId"
56
+ },
57
+ "description": "enabling conditions under which the relation holds"
58
+ },
59
+ "refines": {
60
+ "$ref": "#/$defs/croId",
61
+ "description": "the more partial Causal Relation Object this one enriches (lineage; acyclic; must preserve the parent's specified fields)"
62
+ },
63
+ "skips": {
64
+ "type": "boolean",
65
+ "description": "TRUE asserts that this relation crosses non-adjacent strata WITHOUT being re-encoded at the intervening strata: the absence of a mechanism is a POSITIVE FINDING, not a gap (2.0.0 4.4)"
66
+ }
67
+ },
68
+ "$defs": {
69
+ "croId": {
70
+ "type": "string",
71
+ "pattern": "^causal_relation_object:[0-9a-f]{64}$"
72
+ },
73
+ "occId": {
74
+ "type": "string",
75
+ "pattern": "^occurrent:[0-9a-f]{64}$"
76
+ },
77
+ "temporalWindow": {
78
+ "type": "object",
79
+ "required": [
80
+ "minimum_delay",
81
+ "maximum_delay",
82
+ "unit"
83
+ ],
84
+ "additionalProperties": false,
85
+ "properties": {
86
+ "minimum_delay": {
87
+ "type": "number",
88
+ "minimum": 0
89
+ },
90
+ "maximum_delay": {
91
+ "type": "number",
92
+ "minimum": 0
93
+ },
94
+ "unit": {
95
+ "enum": [
96
+ "instant",
97
+ "seconds",
98
+ "minutes",
99
+ "hours",
100
+ "days",
101
+ "weeks",
102
+ "months",
103
+ "years",
104
+ "ticks"
105
+ ],
106
+ "description": "3.0.0: the wall-clock units carry a fixed seconds mapping; 'ticks' is a discrete, dimensionless ORDINAL unit (a step counter) with NO wall-clock mapping - a tick window is ordered by integer comparison, and a tick window and a wall-clock window are different dimensions that do not compare."
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://causalontology.org/schema/conduit.schema.json",
4
+ "title": "Conduit",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "type",
9
+ "from",
10
+ "to",
11
+ "carries"
12
+ ],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "id": {
16
+ "type": "string",
17
+ "pattern": "^conduit:[0-9a-f]{64}$"
18
+ },
19
+ "type": {
20
+ "const": "conduit"
21
+ },
22
+ "label": {
23
+ "type": "string",
24
+ "pattern": "^[a-z][a-z0-9_]*$",
25
+ "description": "the name of the connection (for example: corticospinal_tract)"
26
+ },
27
+ "from": {
28
+ "type": "string",
29
+ "pattern": "^port:[0-9a-f]{64}$"
30
+ },
31
+ "to": {
32
+ "type": "string",
33
+ "pattern": "^port:[0-9a-f]{64}$"
34
+ },
35
+ "carries": {
36
+ "type": "array",
37
+ "minItems": 1,
38
+ "items": {
39
+ "type": "string",
40
+ "pattern": "^occurrent:[0-9a-f]{64}$"
41
+ },
42
+ "description": "the kinds of occurrent this conduit conducts"
43
+ },
44
+ "transform": {
45
+ "type": "string",
46
+ "pattern": "^causal_relation_object:[0-9a-f]{64}$",
47
+ "description": "OPTIONAL. ABSENT asserts the conduit is TRANSMISSIVE. PRESENT names the Causal Relation Object the conduit performs upon what it carries, asserting the conduit is COMPUTATIONAL."
48
+ },
49
+ "realized_by": {
50
+ "type": "string",
51
+ "pattern": "^[a-z][a-z0-9_]*:.+$",
52
+ "minLength": 3,
53
+ "description": "3.0.0 OPTIONAL. A scheme-qualified REFERENCE, by identity, to the native law or signal that REALIZES this conduit's transform (for example a native rate law a computational conduit stands for, or a runtime signal a transmissive conduit stands for). It is a reference, not an embedded law - the native dynamics stay native; the standard only records the binding. ABSENT (unbound) is legal and identity-preserving; a conduit that carried no realized_by in 2.0.0 keeps its identifier under 3.0.0."
54
+ }
55
+ }
56
+ }