structured-context 0.15.0 → 0.17.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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -13
  3. package/dist/api.d.ts +5 -2
  4. package/dist/api.js +4 -0
  5. package/dist/browser.d.ts +14 -0
  6. package/dist/browser.js +13 -0
  7. package/dist/commands/dump.d.ts +2 -0
  8. package/dist/commands/dump.js +3 -1
  9. package/dist/commands/schemas.d.ts +3 -1
  10. package/dist/commands/schemas.js +25 -53
  11. package/dist/commands/spaces.js +4 -6
  12. package/dist/commands/validate.js +20 -19
  13. package/dist/config/health.d.ts +10 -6
  14. package/dist/config/health.js +11 -44
  15. package/dist/config/index.d.ts +4 -0
  16. package/dist/config/index.js +15 -6
  17. package/dist/filter/augment-nodes.d.ts +2 -2
  18. package/dist/filter/augment-nodes.js +2 -2
  19. package/dist/filter/expand-include.js +2 -2
  20. package/dist/index.js +12 -3
  21. package/dist/judge/context.js +1 -1
  22. package/dist/load-space-graph.js +1 -13
  23. package/dist/plugins/markdown/parse-embedded.js +4 -4
  24. package/dist/plugins/miro/cache.js +1 -1
  25. package/dist/plugins/miro/sync.js +2 -2
  26. package/dist/read/resolve-graph-edges.js +3 -3
  27. package/dist/schema/list-schemas.d.ts +27 -0
  28. package/dist/schema/list-schemas.js +108 -0
  29. package/dist/schema/metadata-contract.d.ts +34 -0
  30. package/dist/schema/metadata-contract.js +2 -2
  31. package/dist/schema/validate-graph.d.ts +2 -2
  32. package/dist/schema/validate-graph.js +4 -4
  33. package/dist/schemas/generated/space-graph/1.json +216 -0
  34. package/dist/schemas/generated/space-graph/latest.json +216 -0
  35. package/dist/space-context.js +11 -1
  36. package/dist/space-graph-data.d.ts +237 -0
  37. package/dist/space-graph-data.js +129 -0
  38. package/dist/space-graph.d.ts +12 -1
  39. package/dist/space-graph.js +25 -1
  40. package/dist/testing.js +3 -3
  41. package/dist/types.d.ts +2 -2
  42. package/docs/concepts.md +8 -4
  43. package/package.json +5 -1
  44. package/schemas/generated/space-graph/1.json +216 -0
  45. package/schemas/generated/space-graph/latest.json +216 -0
@@ -3,10 +3,12 @@ export function buildSpaceGraph(nodes, hierarchy) {
3
3
  const levels = hierarchy?.levels ?? [];
4
4
  const hierarchyTypes = new Set(levels.map((l) => l.type));
5
5
  const rootType = levels[0]?.type;
6
- const isHierarchyEdge = (r) => r.source === 'hierarchy' && r.hierarchy === hierarchy?.name;
6
+ const isHierarchyEdge = (r) => r.kind === 'hierarchy' && r.hierarchy === hierarchy?.name;
7
7
  const nodesMap = new Map();
8
8
  const hierarchyChildrenMap = new Map();
9
9
  const childrenMap = new Map();
10
+ const parentEdgesMap = new Map();
11
+ const childEdgesMap = new Map();
10
12
  const hierarchyRoots = [];
11
13
  const orphans = [];
12
14
  const nonHierarchy = [];
@@ -15,10 +17,18 @@ export function buildSpaceGraph(nodes, hierarchy) {
15
17
  nodesMap.set(node.id, node);
16
18
  hierarchyChildrenMap.set(node.id, []);
17
19
  childrenMap.set(node.id, []);
20
+ parentEdgesMap.set(node.id, []);
21
+ childEdgesMap.set(node.id, []);
18
22
  }
19
23
  // Second pass: build children maps (inverted from resolvedParents)
20
24
  for (const node of nodes) {
21
25
  for (const parentRef of node.resolvedParents) {
26
+ const { id: parentId, ...edgeFields } = parentRef;
27
+ const edge = { parent: parentId, child: node.id, ...edgeFields };
28
+ parentEdgesMap.get(node.id).push(edge);
29
+ if (!childEdgesMap.has(parentId))
30
+ childEdgesMap.set(parentId, []);
31
+ childEdgesMap.get(parentId).push(edge);
22
32
  // All-edges map
23
33
  if (!childrenMap.has(parentRef.id))
24
34
  childrenMap.set(parentRef.id, []);
@@ -78,7 +88,21 @@ export function buildSpaceGraph(nodes, hierarchy) {
78
88
  nonHierarchy,
79
89
  hierarchyChildren: hierarchyChildrenMap,
80
90
  children: childrenMap,
91
+ parentEdges: parentEdgesMap,
92
+ childEdges: childEdgesMap,
81
93
  hierarchyIds,
82
94
  hierarchy,
83
95
  };
84
96
  }
97
+ /** Resolve a hierarchy by name, or the main hierarchy when no name is given. */
98
+ export function selectHierarchy(metadata, name) {
99
+ if (name === undefined)
100
+ return metadata.hierarchy;
101
+ const hierarchies = metadata.hierarchies ?? [];
102
+ const hierarchy = hierarchies.find((h) => h.name === name);
103
+ if (!hierarchy) {
104
+ const available = hierarchies.map((h) => h.name).join(', ');
105
+ throw new Error(`Unknown hierarchy: "${name}".${available ? ` Available: ${available}` : ' The schema defines no hierarchies.'}`);
106
+ }
107
+ return hierarchy;
108
+ }
package/dist/testing.js CHANGED
@@ -3,12 +3,12 @@
3
3
  * Override any field to represent specific edge contexts.
4
4
  */
5
5
  export const makeParentRef = (id, overrides = {}) => {
6
- const source = overrides.source ?? 'hierarchy';
6
+ const kind = overrides.kind ?? 'hierarchy';
7
7
  return {
8
8
  id: id,
9
9
  field: 'parent',
10
- source,
11
- ...(source === 'hierarchy' ? { hierarchy: 'main' } : {}),
10
+ kind,
11
+ ...(kind === 'hierarchy' ? { hierarchy: 'main' } : {}),
12
12
  selfRef: false,
13
13
  fieldOn: 'child',
14
14
  ...overrides,
package/dist/types.d.ts CHANGED
@@ -43,8 +43,8 @@ export type ResolvedParentRef = {
43
43
  /** The field name that contained the wikilink (e.g. 'parent', 'key_activities', 'produces_data'). */
44
44
  field: string;
45
45
  /** Whether this edge originates from a hierarchy level or a relationship definition. */
46
- source: 'hierarchy' | 'relationship';
47
- /** Name of the hierarchy the edge belongs to. Set only when source is 'hierarchy'. */
46
+ kind: 'hierarchy' | 'relationship';
47
+ /** Name of the hierarchy the edge belongs to. Set only when kind is 'hierarchy'. */
48
48
  hierarchy?: string;
49
49
  /** Whether the parent and child are the same node type (self-referential edge). */
50
50
  selfRef: boolean;
package/docs/concepts.md CHANGED
@@ -319,11 +319,15 @@ Each entry is a `ResolvedParentRef` object:
319
319
  |---|---|---|
320
320
  | `id` | `NodeId` | The parent node's `id` |
321
321
  | `field` | `string` | The frontmatter field that held the wikilink |
322
- | `source` | `'hierarchy' \| 'relationship'` | Whether the edge came from a hierarchy level or a relationship |
323
- | `hierarchy` | `string` | Name of the hierarchy the edge belongs to; present only when `source` is `'hierarchy'` |
322
+ | `kind` | `'hierarchy' \| 'relationship'` | Whether the edge came from a hierarchy level or a relationship |
323
+ | `hierarchy` | `string` | Name of the hierarchy the edge belongs to; present only when `kind` is `'hierarchy'` |
324
324
  | `selfRef` | `boolean` | Whether the edge is a same-type (self-referential) parent link |
325
325
 
326
- The `source` and `hierarchy` labels let downstream consumers distinguish edge types and hierarchies without re-inspecting the schema. Validation routes `hierarchy` edges to structural checks within their own hierarchy (parent-type rules, skip-level detection) and `relationship` edges to field reference checks (type-match, missing-target). Tree rendering and rule evaluation use the full set.
326
+ The `kind` and `hierarchy` labels let downstream consumers distinguish edge types and hierarchies without re-inspecting the schema. Validation routes `hierarchy` edges to structural checks within their own hierarchy (parent-type rules, skip-level detection) and `relationship` edges to field reference checks (type-match, missing-target). Tree rendering and rule evaluation use the full set.
327
+
328
+ ### Space graph format
329
+
330
+ The **space graph format** is a space's nodes and hierarchies as plain JSON. A program exports it on one side of a process or network boundary and builds a `SpaceGraph` from it on the other. See [api.md](api.md#space-graph-format).
327
331
 
328
332
  ### Content links
329
333
 
@@ -386,7 +390,7 @@ Each entry in `ancestors[]` or `descendants[]` includes all schema fields of the
386
390
  | Metadata field | Type | Description |
387
391
  |----------------|------|-------------|
388
392
  | `_field` | `string` | The edge field name that connects to this ancestor/descendant |
389
- | `_source` | `'hierarchy' \| 'relationship'` | Whether the edge came from a hierarchy or a relationship |
393
+ | `_kind` | `'hierarchy' \| 'relationship'` | Whether the edge came from a hierarchy or a relationship |
390
394
  | `_hierarchy` | `string` | Hierarchy name; present only for hierarchy edges |
391
395
  | `_selfRef` | `boolean` | Whether the edge is a same-type (self-referential) link |
392
396
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "structured-context",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "Keep your content clean and your thinking clear with assistive tools for structured knowledge",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",
@@ -22,6 +22,10 @@
22
22
  "types": "./dist/api.d.ts",
23
23
  "default": "./dist/api.js"
24
24
  },
25
+ "./browser": {
26
+ "types": "./dist/browser.d.ts",
27
+ "default": "./dist/browser.js"
28
+ },
25
29
  "./types": {
26
30
  "types": "./dist/types.d.ts",
27
31
  "default": "./dist/types.js"
@@ -0,0 +1,216 @@
1
+ {
2
+ "$id": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/space-graph/1.json",
3
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
+ "title": "structured-context space graph",
5
+ "type": "object",
6
+ "properties": {
7
+ "formatVersion": {
8
+ "const": 1
9
+ },
10
+ "hierarchies": {
11
+ "type": "array",
12
+ "items": {
13
+ "type": "object",
14
+ "properties": {
15
+ "name": {
16
+ "type": "string"
17
+ },
18
+ "levels": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "object",
22
+ "properties": {
23
+ "type": {
24
+ "type": "string"
25
+ },
26
+ "field": {
27
+ "type": "string",
28
+ "minLength": 1
29
+ },
30
+ "fieldOn": {
31
+ "enum": ["child", "parent"]
32
+ },
33
+ "multiple": {
34
+ "type": "boolean"
35
+ },
36
+ "templateFormat": {
37
+ "enum": ["heading", "list", "table", "page"]
38
+ },
39
+ "matchers": {
40
+ "type": "array",
41
+ "items": {
42
+ "type": "string",
43
+ "minLength": 1
44
+ },
45
+ "minItems": 1
46
+ },
47
+ "embeddedTemplateFields": {
48
+ "type": "array",
49
+ "items": {
50
+ "type": "string",
51
+ "minLength": 1
52
+ }
53
+ },
54
+ "selfRef": {
55
+ "type": "boolean"
56
+ },
57
+ "selfRefField": {
58
+ "type": "string"
59
+ }
60
+ },
61
+ "required": ["type", "field", "fieldOn", "multiple", "selfRef"],
62
+ "additionalProperties": false
63
+ }
64
+ },
65
+ "allowSkipLevels": {
66
+ "type": "boolean"
67
+ }
68
+ },
69
+ "required": ["name", "levels"],
70
+ "additionalProperties": false
71
+ }
72
+ },
73
+ "mainHierarchy": {
74
+ "type": "string"
75
+ },
76
+ "nodes": {
77
+ "type": "array",
78
+ "items": {
79
+ "type": "object",
80
+ "properties": {
81
+ "id": {
82
+ "type": "string"
83
+ },
84
+ "title": {
85
+ "type": "string"
86
+ },
87
+ "schemaData": {
88
+ "type": "object"
89
+ },
90
+ "linkTargets": {
91
+ "type": "array",
92
+ "items": {
93
+ "type": "string"
94
+ }
95
+ },
96
+ "type": {
97
+ "type": "string"
98
+ },
99
+ "content": {
100
+ "type": "string"
101
+ },
102
+ "contentLinks": {
103
+ "type": "array",
104
+ "items": {
105
+ "type": "object",
106
+ "properties": {
107
+ "text": {
108
+ "type": "string"
109
+ },
110
+ "target": {
111
+ "type": "string"
112
+ },
113
+ "action": {
114
+ "enum": ["link", "embed"]
115
+ },
116
+ "anchor": {
117
+ "type": "string"
118
+ },
119
+ "linkSyntax": {
120
+ "enum": ["wikilink", "markdown"]
121
+ }
122
+ },
123
+ "required": ["text", "target", "action", "linkSyntax"],
124
+ "additionalProperties": false
125
+ }
126
+ },
127
+ "source": {
128
+ "type": "object",
129
+ "properties": {
130
+ "file": {
131
+ "type": "string"
132
+ },
133
+ "line": {
134
+ "type": "integer"
135
+ },
136
+ "column": {
137
+ "type": "integer"
138
+ }
139
+ },
140
+ "required": ["file"],
141
+ "additionalProperties": false
142
+ },
143
+ "resolvedType": {
144
+ "type": "string"
145
+ },
146
+ "resolvedParents": {
147
+ "type": "array",
148
+ "items": {
149
+ "type": "object",
150
+ "properties": {
151
+ "id": {
152
+ "type": "string"
153
+ },
154
+ "field": {
155
+ "type": "string"
156
+ },
157
+ "kind": {
158
+ "enum": ["hierarchy", "relationship"]
159
+ },
160
+ "hierarchy": {
161
+ "type": "string"
162
+ },
163
+ "selfRef": {
164
+ "type": "boolean"
165
+ },
166
+ "fieldOn": {
167
+ "enum": ["child", "parent"]
168
+ }
169
+ },
170
+ "required": ["id", "field", "kind", "selfRef", "fieldOn"],
171
+ "additionalProperties": false
172
+ }
173
+ },
174
+ "resolvedLinks": {
175
+ "type": "array",
176
+ "items": {
177
+ "type": "object",
178
+ "properties": {
179
+ "text": {
180
+ "type": "string"
181
+ },
182
+ "target": {
183
+ "type": "string"
184
+ },
185
+ "action": {
186
+ "enum": ["link", "embed"]
187
+ },
188
+ "anchor": {
189
+ "type": "string"
190
+ },
191
+ "location": {
192
+ "enum": ["node", "internal", "external", "system", "protocol"]
193
+ }
194
+ },
195
+ "required": ["text", "target", "action", "location"],
196
+ "additionalProperties": false
197
+ }
198
+ }
199
+ },
200
+ "required": [
201
+ "id",
202
+ "title",
203
+ "schemaData",
204
+ "linkTargets",
205
+ "type",
206
+ "resolvedType",
207
+ "resolvedParents",
208
+ "resolvedLinks"
209
+ ],
210
+ "additionalProperties": false
211
+ }
212
+ }
213
+ },
214
+ "required": ["formatVersion", "hierarchies", "nodes"],
215
+ "additionalProperties": false
216
+ }
@@ -0,0 +1,216 @@
1
+ {
2
+ "$id": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/space-graph/1.json",
3
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4
+ "title": "structured-context space graph",
5
+ "type": "object",
6
+ "properties": {
7
+ "formatVersion": {
8
+ "const": 1
9
+ },
10
+ "hierarchies": {
11
+ "type": "array",
12
+ "items": {
13
+ "type": "object",
14
+ "properties": {
15
+ "name": {
16
+ "type": "string"
17
+ },
18
+ "levels": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "object",
22
+ "properties": {
23
+ "type": {
24
+ "type": "string"
25
+ },
26
+ "field": {
27
+ "type": "string",
28
+ "minLength": 1
29
+ },
30
+ "fieldOn": {
31
+ "enum": ["child", "parent"]
32
+ },
33
+ "multiple": {
34
+ "type": "boolean"
35
+ },
36
+ "templateFormat": {
37
+ "enum": ["heading", "list", "table", "page"]
38
+ },
39
+ "matchers": {
40
+ "type": "array",
41
+ "items": {
42
+ "type": "string",
43
+ "minLength": 1
44
+ },
45
+ "minItems": 1
46
+ },
47
+ "embeddedTemplateFields": {
48
+ "type": "array",
49
+ "items": {
50
+ "type": "string",
51
+ "minLength": 1
52
+ }
53
+ },
54
+ "selfRef": {
55
+ "type": "boolean"
56
+ },
57
+ "selfRefField": {
58
+ "type": "string"
59
+ }
60
+ },
61
+ "required": ["type", "field", "fieldOn", "multiple", "selfRef"],
62
+ "additionalProperties": false
63
+ }
64
+ },
65
+ "allowSkipLevels": {
66
+ "type": "boolean"
67
+ }
68
+ },
69
+ "required": ["name", "levels"],
70
+ "additionalProperties": false
71
+ }
72
+ },
73
+ "mainHierarchy": {
74
+ "type": "string"
75
+ },
76
+ "nodes": {
77
+ "type": "array",
78
+ "items": {
79
+ "type": "object",
80
+ "properties": {
81
+ "id": {
82
+ "type": "string"
83
+ },
84
+ "title": {
85
+ "type": "string"
86
+ },
87
+ "schemaData": {
88
+ "type": "object"
89
+ },
90
+ "linkTargets": {
91
+ "type": "array",
92
+ "items": {
93
+ "type": "string"
94
+ }
95
+ },
96
+ "type": {
97
+ "type": "string"
98
+ },
99
+ "content": {
100
+ "type": "string"
101
+ },
102
+ "contentLinks": {
103
+ "type": "array",
104
+ "items": {
105
+ "type": "object",
106
+ "properties": {
107
+ "text": {
108
+ "type": "string"
109
+ },
110
+ "target": {
111
+ "type": "string"
112
+ },
113
+ "action": {
114
+ "enum": ["link", "embed"]
115
+ },
116
+ "anchor": {
117
+ "type": "string"
118
+ },
119
+ "linkSyntax": {
120
+ "enum": ["wikilink", "markdown"]
121
+ }
122
+ },
123
+ "required": ["text", "target", "action", "linkSyntax"],
124
+ "additionalProperties": false
125
+ }
126
+ },
127
+ "source": {
128
+ "type": "object",
129
+ "properties": {
130
+ "file": {
131
+ "type": "string"
132
+ },
133
+ "line": {
134
+ "type": "integer"
135
+ },
136
+ "column": {
137
+ "type": "integer"
138
+ }
139
+ },
140
+ "required": ["file"],
141
+ "additionalProperties": false
142
+ },
143
+ "resolvedType": {
144
+ "type": "string"
145
+ },
146
+ "resolvedParents": {
147
+ "type": "array",
148
+ "items": {
149
+ "type": "object",
150
+ "properties": {
151
+ "id": {
152
+ "type": "string"
153
+ },
154
+ "field": {
155
+ "type": "string"
156
+ },
157
+ "kind": {
158
+ "enum": ["hierarchy", "relationship"]
159
+ },
160
+ "hierarchy": {
161
+ "type": "string"
162
+ },
163
+ "selfRef": {
164
+ "type": "boolean"
165
+ },
166
+ "fieldOn": {
167
+ "enum": ["child", "parent"]
168
+ }
169
+ },
170
+ "required": ["id", "field", "kind", "selfRef", "fieldOn"],
171
+ "additionalProperties": false
172
+ }
173
+ },
174
+ "resolvedLinks": {
175
+ "type": "array",
176
+ "items": {
177
+ "type": "object",
178
+ "properties": {
179
+ "text": {
180
+ "type": "string"
181
+ },
182
+ "target": {
183
+ "type": "string"
184
+ },
185
+ "action": {
186
+ "enum": ["link", "embed"]
187
+ },
188
+ "anchor": {
189
+ "type": "string"
190
+ },
191
+ "location": {
192
+ "enum": ["node", "internal", "external", "system", "protocol"]
193
+ }
194
+ },
195
+ "required": ["text", "target", "action", "location"],
196
+ "additionalProperties": false
197
+ }
198
+ }
199
+ },
200
+ "required": [
201
+ "id",
202
+ "title",
203
+ "schemaData",
204
+ "linkTargets",
205
+ "type",
206
+ "resolvedType",
207
+ "resolvedParents",
208
+ "resolvedLinks"
209
+ ],
210
+ "additionalProperties": false
211
+ }
212
+ }
213
+ },
214
+ "required": ["formatVersion", "hierarchies", "nodes"],
215
+ "additionalProperties": false
216
+ }