structured-context 0.11.0 → 0.13.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.
- package/README.md +52 -198
- package/dist/api.d.ts +17 -15
- package/dist/api.js +12 -9
- package/dist/commands/diagram.d.ts +1 -0
- package/dist/commands/diagram.js +7 -1
- package/dist/commands/docs.js +1 -0
- package/dist/commands/dump.d.ts +15 -2
- package/dist/commands/dump.js +18 -4
- package/dist/commands/providers.d.ts +4 -0
- package/dist/commands/providers.js +52 -0
- package/dist/commands/render.d.ts +4 -0
- package/dist/commands/render.js +64 -9
- package/dist/commands/schemas.d.ts +2 -2
- package/dist/commands/schemas.js +133 -22
- package/dist/commands/show.d.ts +1 -0
- package/dist/commands/show.js +7 -1
- package/dist/commands/spaces.d.ts +3 -1
- package/dist/commands/spaces.js +11 -2
- package/dist/commands/validate-file.d.ts +3 -0
- package/dist/commands/validate-file.js +24 -6
- package/dist/commands/validate.d.ts +4 -0
- package/dist/commands/validate.js +79 -23
- package/dist/config.d.ts +25 -1
- package/dist/config.js +106 -12
- package/dist/filter/augment-nodes.d.ts +3 -1
- package/dist/filter/augment-nodes.js +12 -7
- package/dist/filter/filter-nodes.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +96 -31
- package/dist/judge/context.d.ts +20 -0
- package/dist/judge/context.js +105 -0
- package/dist/judge/factory.d.ts +44 -0
- package/dist/judge/factory.js +148 -0
- package/dist/judge/index.d.ts +13 -0
- package/dist/judge/index.js +8 -0
- package/dist/judge/judge-node.d.ts +27 -0
- package/dist/judge/judge-node.js +122 -0
- package/dist/judge/prompt.d.ts +10 -0
- package/dist/judge/prompt.js +92 -0
- package/dist/judge/provider/anthropic.d.ts +17 -0
- package/dist/judge/provider/anthropic.js +43 -0
- package/dist/judge/provider/fake.d.ts +26 -0
- package/dist/judge/provider/fake.js +56 -0
- package/dist/judge/provider/jev.d.ts +37 -0
- package/dist/judge/provider/jev.js +169 -0
- package/dist/judge/provider/openai-decisions.d.ts +21 -0
- package/dist/judge/provider/openai-decisions.js +84 -0
- package/dist/judge/provider/openai.d.ts +20 -0
- package/dist/judge/provider/openai.js +53 -0
- package/dist/judge/provider/per-rule.d.ts +10 -0
- package/dist/judge/provider/per-rule.js +18 -0
- package/dist/judge/trim.d.ts +27 -0
- package/dist/judge/trim.js +62 -0
- package/dist/judge/types.d.ts +92 -0
- package/dist/judge/types.js +9 -0
- package/dist/judge/verdicts.d.ts +24 -0
- package/dist/judge/verdicts.js +82 -0
- package/dist/load-space-graph.d.ts +7 -5
- package/dist/load-space-graph.js +19 -8
- package/dist/plugins/loader.js +3 -3
- package/dist/plugins/markdown/extract-content-links.js +8 -29
- package/dist/plugins/markdown/index.js +8 -2
- package/dist/plugins/markdown/parse-embedded.d.ts +8 -0
- package/dist/plugins/markdown/parse-embedded.js +195 -24
- package/dist/plugins/markdown/read-space.js +42 -14
- package/dist/plugins/markdown/render-directory.d.ts +11 -0
- package/dist/plugins/markdown/render-directory.js +130 -0
- package/dist/plugins/markdown/template-sync.js +3 -4
- package/dist/plugins/markdown/util.d.ts +26 -5
- package/dist/plugins/markdown/util.js +56 -15
- package/dist/plugins/mermaid/render-mermaid.js +2 -1
- package/dist/plugins/miro/sync.js +7 -6
- package/dist/plugins/util.d.ts +39 -1
- package/dist/plugins/util.js +139 -0
- package/dist/read/resolve-graph-edges.d.ts +1 -1
- package/dist/read/resolve-graph-edges.js +46 -27
- package/dist/read/wikilink-utils.d.ts +17 -0
- package/dist/read/wikilink-utils.js +40 -0
- package/dist/render/render.d.ts +3 -1
- package/dist/render/render.js +2 -2
- package/dist/schema/evaluate-rule.d.ts +33 -2
- package/dist/schema/evaluate-rule.js +58 -4
- package/dist/schema/gating.d.ts +69 -0
- package/dist/schema/gating.js +253 -0
- package/dist/schema/meta-schemas.d.ts +13 -0
- package/dist/schema/meta-schemas.js +50 -0
- package/dist/schema/metadata-contract.d.ts +952 -183
- package/dist/schema/metadata-contract.js +177 -33
- package/dist/schema/rule-filter.d.ts +12 -0
- package/dist/schema/rule-filter.js +46 -0
- package/dist/schema/rule-severity.d.ts +13 -0
- package/dist/schema/rule-severity.js +33 -0
- package/dist/schema/schema.d.ts +14 -8
- package/dist/schema/schema.js +308 -199
- package/dist/schema/validate-graph.d.ts +2 -1
- package/dist/schema/validate-graph.js +40 -23
- package/dist/schema/validate-rules.d.ts +16 -3
- package/dist/schema/validate-rules.js +91 -29
- package/dist/schemas/_knowledge_wiki.json +24 -24
- package/dist/schemas/_okf.json +172 -0
- package/dist/schemas/_ost_strict.json +17 -8
- package/dist/schemas/_sctx_base.json +3 -3
- package/dist/schemas/_strategy_general.json +38 -38
- package/dist/schemas/generated/0.12.0/_structured_context_schema_meta.json +229 -0
- package/dist/schemas/generated/0.13.0/_structured_context_schema_meta.json +400 -0
- package/dist/schemas/generated/latest/_structured_context_schema_meta.json +400 -0
- package/dist/schemas/knowledge_wiki.json +10 -9
- package/dist/schemas/okf.json +8 -0
- package/dist/schemas/strategy_general.json +15 -14
- package/dist/schemas/strict_ost.json +17 -16
- package/dist/space-context.d.ts +5 -2
- package/dist/space-context.js +9 -4
- package/dist/space-graph.d.ts +9 -7
- package/dist/space-graph.js +7 -5
- package/dist/testing.d.ts +33 -0
- package/dist/testing.js +72 -0
- package/dist/types.d.ts +64 -16
- package/dist/validate.d.ts +62 -9
- package/dist/validate.js +229 -114
- package/docs/concepts.md +65 -9
- package/docs/config.md +78 -1
- package/docs/rules.md +168 -50
- package/docs/schemas.md +152 -52
- package/package.json +17 -11
- package/schemas/_knowledge_wiki.json +24 -24
- package/schemas/_okf.json +172 -0
- package/schemas/_ost_strict.json +17 -8
- package/schemas/_sctx_base.json +3 -3
- package/schemas/_strategy_general.json +38 -38
- package/schemas/generated/0.12.0/_structured_context_schema_meta.json +229 -0
- package/schemas/generated/0.13.0/_structured_context_schema_meta.json +400 -0
- package/schemas/generated/latest/_structured_context_schema_meta.json +400 -0
- package/schemas/knowledge_wiki.json +10 -9
- package/schemas/okf.json +8 -0
- package/schemas/strategy_general.json +15 -14
- package/schemas/strict_ost.json +17 -16
- package/dist/schemas/generated/_structured_context_schema_meta.json +0 -191
- package/schemas/generated/_structured_context_schema_meta.json +0 -191
package/docs/schemas.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Schemas"
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Schemas
|
|
2
6
|
|
|
3
7
|
This document explains schema usage, metadata shape, and composition semantics in `structured-context`.
|
|
@@ -6,7 +10,7 @@ This document explains schema usage, metadata shape, and composition semantics i
|
|
|
6
10
|
|
|
7
11
|
A **schema** defines the valid structure for nodes in a `space`: entity types, field constraints, hierarchy behavior, type aliases, and executable rules.
|
|
8
12
|
|
|
9
|
-
`structured-context` uses JSON Schema
|
|
13
|
+
`structured-context` uses JSON Schema 2020-12 plus a custom top-level `$metadata` keyword.
|
|
10
14
|
|
|
11
15
|
## Selecting a schema
|
|
12
16
|
|
|
@@ -20,6 +24,11 @@ Set `schema` in the space config entry:
|
|
|
20
24
|
}
|
|
21
25
|
```
|
|
22
26
|
|
|
27
|
+
A schema can be specified as:
|
|
28
|
+
- **Bundled schema**: simple filename like `strategy_general.json` or `strict_ost.json`.
|
|
29
|
+
- **Local file**: relative path starting with `./` or `../` (resolved against config file directory), or absolute path.
|
|
30
|
+
- **Plugin schema**: prefixed with the plugin name, e.g. `sctx-wardley-mapping/wardley_map.json` or `wardley-mapping/wardley_map.json`. When prefixed, structured-context automatically loads the plugin for that space. Alternatively, if the plugin is already declared under `plugins`, the simple filename (e.g. `wardley_map.json`) resolves directly from that plugin.
|
|
31
|
+
|
|
23
32
|
Resolution order: space `schema` > global `schema`. Schema resolution fails if none is configured.
|
|
24
33
|
|
|
25
34
|
## Bundled schemas
|
|
@@ -46,7 +55,23 @@ Main types:
|
|
|
46
55
|
- `solution`
|
|
47
56
|
- `assumption_test`
|
|
48
57
|
|
|
49
|
-
This schema
|
|
58
|
+
This schema reuses shared structural defs from partials via `$ref` and imports its hierarchy and rules from `_ost_strict` via `$metadata.imports`.
|
|
59
|
+
|
|
60
|
+
### `knowledge_wiki.json`
|
|
61
|
+
|
|
62
|
+
Flat, LLM-maintained knowledge base (after Karpathy's LLM Wiki pattern). No hierarchy or required parent links; wikilinks between any pages are valid. Validates structure and provenance, not meaning.
|
|
63
|
+
|
|
64
|
+
Main types:
|
|
65
|
+
- `source`
|
|
66
|
+
- `concept`
|
|
67
|
+
- `entity`
|
|
68
|
+
- `synthesis`
|
|
69
|
+
- `note`
|
|
70
|
+
- `index`
|
|
71
|
+
|
|
72
|
+
### `okf.json`
|
|
73
|
+
|
|
74
|
+
[Open Knowledge Format](https://github.com/GoogleCloudPlatform/open-knowledge-format) (OKF v0.2) bundles, validated as plain markdown spaces. Any concept `type` is accepted and unknown fields are tolerated; provenance (`sources`), trust (`generated`, `verified`), lifecycle (`status`, `stale_after`) and the Attested Computation contract are checked when present. An Attested Computation needs its computation: a `computation` field, or a `# Computation` section in the body (found by matching that line in the body text, so a `# Computation` line inside a code fence also counts). Reserved `index.md` and `log.md` are reported as excluded during parsing.
|
|
50
75
|
|
|
51
76
|
## Custom format annotations
|
|
52
77
|
|
|
@@ -54,14 +79,16 @@ This schema composes shared structural defs and strict metadata/rules from parti
|
|
|
54
79
|
|
|
55
80
|
| Format | Validates | Example |
|
|
56
81
|
|--------|-----------|---------|
|
|
57
|
-
| `date` | ISO 8601 date (`YYYY-MM-DD`) | `"2026-03-31"` |
|
|
82
|
+
| `date` | ISO 8601 calendar date (`YYYY-MM-DD`) | `"2026-03-31"` |
|
|
83
|
+
| `date-time` | ISO 8601 datetime with seconds and a UTC offset (`Z` or `±HH:MM`) | `"2026-03-31T09:15:00+10:00"` |
|
|
84
|
+
| `date-or-date-time` | A date, or a datetime where seconds and offset are optional (as Obsidian's datetime property writes) | `"2026-03-31"`, `"2026-03-31T09:15"`, `"2026-03-31T09:15:00Z"` |
|
|
58
85
|
| `path` | Non-empty filesystem path — absolute, relative, or a plain name | `"notes"`, `"./subdir/file.md"`, `"/abs/path"` |
|
|
59
86
|
| `wikilink` | Obsidian wikilink syntax (`[[...]]`) | `"[[Parent Node]]"` |
|
|
60
87
|
|
|
61
88
|
`path` and `wikilink` are also available as shared `$ref` definitions in `_sctx_base.json`:
|
|
62
89
|
|
|
63
90
|
```json
|
|
64
|
-
{ "$ref": "sctx://_sctx_base#/$defs/wikilink" }
|
|
91
|
+
{ "$ref": "sctx://core/_sctx_base#/$defs/wikilink" }
|
|
65
92
|
```
|
|
66
93
|
|
|
67
94
|
Using `format` directly is more concise when the full definition isn't needed:
|
|
@@ -70,21 +97,25 @@ Using `format` directly is more concise when the full definition isn't needed:
|
|
|
70
97
|
{ "type": "string", "format": "wikilink" }
|
|
71
98
|
```
|
|
72
99
|
|
|
73
|
-
###
|
|
100
|
+
### Dates and datetimes
|
|
74
101
|
|
|
75
|
-
YAML
|
|
102
|
+
The markdown plugin reads frontmatter and embedded YAML blocks without YAML's timestamp type, so unquoted dates and datetimes stay as the strings written, at any depth (including inside lists):
|
|
76
103
|
|
|
77
104
|
```yaml
|
|
78
|
-
published_date: 2026-03-31
|
|
105
|
+
published_date: 2026-03-31 # "2026-03-31"
|
|
106
|
+
updated: 2026-06-20T22:53:05+10:00 # "2026-06-20T22:53:05+10:00", offset kept
|
|
79
107
|
```
|
|
80
108
|
|
|
81
|
-
|
|
109
|
+
Validate them with `format: "date"` or `format: "date-time"` when a field needs one precision, or `format: "date-or-date-time"` to accept either, and compare them in rules with JSONata's `$toMillis()` (see [Rules](rules.md#dates-and-times)).
|
|
82
110
|
|
|
83
111
|
## Metadata dialect
|
|
84
112
|
|
|
85
|
-
Schemas
|
|
113
|
+
The dialect is JSON Schema 2020-12 plus the top-level `$metadata` keyword. Schemas set `$schema` to the metaschema URL:
|
|
114
|
+
|
|
115
|
+
- `https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/latest/_structured_context_schema_meta.json` follows the newest dialect.
|
|
116
|
+
- `https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/<version>/_structured_context_schema_meta.json` pins the dialect to the structured-context release that first shipped it. Versioned files never change once released. Releases that don't change the dialect add no folder, so a version number only appears when the dialect changed.
|
|
86
117
|
|
|
87
|
-
- `
|
|
118
|
+
Because the dialect is 2020-12, keywords may sit beside `$ref`, and `unevaluatedProperties: false` can close an object composed through `allOf`.
|
|
88
119
|
|
|
89
120
|
Top-level metadata shape:
|
|
90
121
|
|
|
@@ -108,8 +139,8 @@ Top-level metadata shape:
|
|
|
108
139
|
"id": "active-outcome-count",
|
|
109
140
|
"category": "workflow",
|
|
110
141
|
"description": "Only one outcome should be active at a time",
|
|
111
|
-
"
|
|
112
|
-
"
|
|
142
|
+
"global": true,
|
|
143
|
+
"expression": "$count(nodes[resolvedType='outcome' and status='active']) <= 1"
|
|
113
144
|
}
|
|
114
145
|
]
|
|
115
146
|
}
|
|
@@ -120,12 +151,15 @@ Top-level metadata shape:
|
|
|
120
151
|
|
|
121
152
|
| Field | Type | Notes |
|
|
122
153
|
|---|---|---|
|
|
123
|
-
| `
|
|
154
|
+
| `imports` | `string[]` | Optional; `$id`s of schemas whose metadata is merged into this one. See [Composition and merge semantics](#composition-and-merge-semantics) |
|
|
155
|
+
| `hierarchy` | object | Optional; declares this schema's hierarchy, or (root schema only) selects the main hierarchy with `{ "$ref": "<schema $id>#/$metadata/hierarchy" }`. See [Multiple hierarchies](#multiple-hierarchies) |
|
|
156
|
+
| `hierarchy.name` | `string` | Optional short name; defaults to the declaring schema's file stem |
|
|
157
|
+
| `hierarchy.override` | `boolean` | Optional; replaces an imported hierarchy with the same name |
|
|
124
158
|
| `hierarchy.levels` | `(string \| HierarchyLevel)[]` | Ordered root→leaf types |
|
|
125
159
|
| `hierarchy.allowSkipLevels` | `boolean` | Optional; allows parent to be any ancestor level |
|
|
126
|
-
| `relationships` | `Relationship[]` | Optional; defines related node links outside the primary hierarchy |
|
|
127
|
-
| `aliases` | `Record<string, string>` | Optional type alias map |
|
|
128
|
-
| `rules` | `Rule[]` | Optional flat rule array |
|
|
160
|
+
| `relationships` | `Relationship[]` | Optional; defines related node links outside the primary hierarchy. A relationship may set `override: true` |
|
|
161
|
+
| `aliases` | `Record<string, string \| { type, override }>` | Optional type alias map. Use `{ "type": "goal", "override": true }` to replace an imported alias |
|
|
162
|
+
| `rules` | `Rule[]` | Optional flat rule array. A rule has an `expression` (a JSONata test), a `semantic` part (evaluated by a model against a rubric), or both; see [Rules](rules.md) |
|
|
129
163
|
|
|
130
164
|
### Relationships
|
|
131
165
|
|
|
@@ -137,9 +171,9 @@ Relationships define links between node types that are not part of the primary s
|
|
|
137
171
|
| `type` | `string` | **Required** | The child's canonical type name |
|
|
138
172
|
| `field` | `string` | `"parent"` | The frontmatter field that holds the wikilink(s) for this relationship |
|
|
139
173
|
| `fieldOn` | `string` | `"child"` | `"child"` (child holds a link to parent) or `"parent"` (parent holds an array of child links) |
|
|
140
|
-
| `
|
|
174
|
+
| `templateFormat` | `string` | `"page"` | Hint for `template-sync`: `"table"`, `"list"`, or `"heading"` |
|
|
141
175
|
| `matchers` | `string[]` | `[]` | Heading text to match (strings or `/regex/`). Case-insensitive. |
|
|
142
|
-
| `embeddedTemplateFields` | `string[]` | `[]` | Field names to include in templates when `
|
|
176
|
+
| `embeddedTemplateFields` | `string[]` | `[]` | Field names to include in templates when `templateFormat` is `"table"` |
|
|
143
177
|
| `multiple` | `boolean` | `true` | Whether multiple children are expected |
|
|
144
178
|
|
|
145
179
|
**`fieldOn: "child"` (default)** — child node has a field pointing to its parent. Embedded parsing sets this field on each child node; validation checks that it resolves to a node of the declared parent type.
|
|
@@ -153,7 +187,7 @@ Relationships define links between node types that are not part of the primary s
|
|
|
153
187
|
{
|
|
154
188
|
"parent": "opportunity",
|
|
155
189
|
"type": "assumption",
|
|
156
|
-
"
|
|
190
|
+
"templateFormat": "table",
|
|
157
191
|
"matchers": ["Assumptions", "/assum.*/"],
|
|
158
192
|
"embeddedTemplateFields": ["assumption", "status", "confidence"]
|
|
159
193
|
}
|
|
@@ -169,7 +203,7 @@ Relationships define links between node types that are not part of the primary s
|
|
|
169
203
|
"type": "task",
|
|
170
204
|
"field": "tasks",
|
|
171
205
|
"fieldOn": "parent",
|
|
172
|
-
"
|
|
206
|
+
"templateFormat": "list",
|
|
173
207
|
"matchers": ["Tasks"],
|
|
174
208
|
"multiple": true
|
|
175
209
|
}
|
|
@@ -188,7 +222,7 @@ With this configuration, embedded task items under an Activity's "Tasks" heading
|
|
|
188
222
|
| `multiple` | `false` | Field contains array of wikilinks |
|
|
189
223
|
| `selfRef` | `false` | Allows same-type parent |
|
|
190
224
|
| `selfRefField` | _undefined_ | Separate field for same-type parent links |
|
|
191
|
-
| `
|
|
225
|
+
| `templateFormat` | _undefined_ | Embedding hint: `"list"`, `"table"`, or `"heading"` — enables hierarchy embedding when set |
|
|
192
226
|
| `matchers` | _undefined_ | Heading text patterns (strings or `/regex/`) to detect embedding sections |
|
|
193
227
|
| `embeddedTemplateFields` | _undefined_ | Column/field names for table stubs generated by `template-sync` |
|
|
194
228
|
|
|
@@ -197,7 +231,7 @@ String shorthand (`"goal"`) normalizes to:
|
|
|
197
231
|
|
|
198
232
|
### Hierarchy embedding
|
|
199
233
|
|
|
200
|
-
When a hierarchy level has `
|
|
234
|
+
When a hierarchy level has `templateFormat` and `matchers`, it participates in **hierarchy embedding** — the same section-based parsing used for relationships. Two patterns are supported:
|
|
201
235
|
|
|
202
236
|
**Child-level embedding** — a typed-page heading signals that following content should produce nodes of the child type (next level in hierarchy):
|
|
203
237
|
|
|
@@ -208,7 +242,7 @@ When a hierarchy level has `format` and `matchers`, it participates in **hierarc
|
|
|
208
242
|
"type": "opportunity",
|
|
209
243
|
"field": "parent",
|
|
210
244
|
"fieldOn": "child",
|
|
211
|
-
"
|
|
245
|
+
"templateFormat": "list",
|
|
212
246
|
"matchers": ["Opportunities", "User Opportunities"]
|
|
213
247
|
}
|
|
214
248
|
]
|
|
@@ -250,39 +284,79 @@ With this config, an application page may include `### capability` with wikilink
|
|
|
250
284
|
- [[Zephyr]] ← populates application.tools (fieldOn: parent)
|
|
251
285
|
```
|
|
252
286
|
|
|
287
|
+
A node's body becomes its `content`; see [Node content](concepts.md#node-content).
|
|
288
|
+
|
|
253
289
|
## Composition and merge semantics
|
|
254
290
|
|
|
255
|
-
|
|
291
|
+
`$ref` and `$defs` are for **validation only**: a `$ref` to another schema (or to one of its `$defs`) reuses its JSON Schema definitions but brings none of its `$metadata`.
|
|
292
|
+
|
|
293
|
+
Metadata travels only through **`$metadata.imports`**, a list of schema `$id`s:
|
|
294
|
+
|
|
295
|
+
```json5
|
|
296
|
+
"$metadata": {
|
|
297
|
+
"imports": ["sctx://core/_strategy_general"],
|
|
298
|
+
"rules": [ /* this schema's own rules */ ]
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
- An import brings the imported schema's whole `$metadata` (hierarchy, relationships, aliases, rules).
|
|
303
|
+
- Imports are transitive: an imported schema's own imports come too.
|
|
304
|
+
- Merge order: imports in the order listed, depth-first, then the schema's own metadata last. Each schema is merged at most once.
|
|
305
|
+
- An unresolvable import `$id` is an error.
|
|
256
306
|
|
|
257
|
-
|
|
258
|
-
2. Apply root schema metadata last.
|
|
307
|
+
One merge rule applies to every key. **A duplicate is an error unless the later entry sets `"override": true`**, in which case it replaces the earlier entry.
|
|
259
308
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
309
|
+
| Key | Identity | How to mark `override` |
|
|
310
|
+
|---|---|---|
|
|
311
|
+
| `rules` | `id` | `"override": true` on the rule |
|
|
312
|
+
| `relationships` | `parent` + `type` + `field` (default `"parent"`) | `"override": true` on the relationship |
|
|
313
|
+
| `aliases` | alias name | `{ "type": "<target>", "override": true }` as the alias value |
|
|
314
|
+
| `hierarchy` | `name` | `"override": true` on the hierarchy declaration |
|
|
315
|
+
|
|
316
|
+
Overriding a hierarchy by name is how a schema replaces the levels of an imported hierarchy (declare it with the same `name` and `"override": true`).
|
|
267
317
|
|
|
268
318
|
When no provider defines `hierarchy`, hierarchy-based behavior is disabled (`show` tree shape, hierarchy validation, parent-edge checks). `space_on_a_page` parsing still requires hierarchy and will error without it.
|
|
269
319
|
|
|
270
|
-
###
|
|
320
|
+
### Multiple hierarchies
|
|
321
|
+
|
|
322
|
+
A space has several hierarchies when its schema imports several schemas that each declare one. Each schema declares at most one hierarchy.
|
|
271
323
|
|
|
272
|
-
|
|
324
|
+
- **Every imported schema contributes its hierarchy.** Each is kept as a separate named hierarchy; levels are never merged.
|
|
325
|
+
- **Naming.** `hierarchy.name` defaults to the declaring schema's file stem (`_ost_strict` for `_ost_strict.json`). A duplicate name is an error unless the later hierarchy sets `"override": true`.
|
|
326
|
+
- **Main hierarchy.**
|
|
327
|
+
- If the root schema declares a hierarchy, it is the main hierarchy.
|
|
328
|
+
- If the root declares none and exactly one hierarchy is imported, that one is the main hierarchy (for example `strict_ost`, which imports `_ost_strict`).
|
|
329
|
+
- If the root declares none and several are imported, the root must select one with `"hierarchy": { "$ref": "<schema $id>#/$metadata/hierarchy" }`, otherwise loading the schema fails.
|
|
330
|
+
- A root that both declares a hierarchy and uses `$ref` is an error.
|
|
331
|
+
- **Each type belongs to at most one hierarchy.** A type claimed by two hierarchies is an error. To change an imported hierarchy's levels, override it by name.
|
|
332
|
+
- **Selections are not imported.** A `hierarchy: { "$ref" }` selection only applies when its schema is the root, so an imported schema stays usable standalone as another space's root.
|
|
273
333
|
|
|
274
334
|
```json5
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
335
|
+
{
|
|
336
|
+
"$id": "sctx://team",
|
|
337
|
+
"oneOf": [
|
|
338
|
+
{ "$ref": "sctx://_work#/$defs/goal" },
|
|
339
|
+
{ "$ref": "sctx://_work#/$defs/task" },
|
|
340
|
+
{ "$ref": "sctx://_skills#/$defs/skill_area" },
|
|
341
|
+
{ "$ref": "sctx://_skills#/$defs/skill" }
|
|
342
|
+
],
|
|
343
|
+
"$metadata": {
|
|
344
|
+
// _work.json and _skills.json each declare a hierarchy; select the main one.
|
|
345
|
+
"imports": ["sctx://_work", "sctx://_skills"],
|
|
346
|
+
"hierarchy": { "$ref": "sctx://_work#/$metadata/hierarchy" }
|
|
347
|
+
}
|
|
348
|
+
}
|
|
279
349
|
```
|
|
280
350
|
|
|
281
|
-
|
|
282
|
-
- a single rule object
|
|
283
|
-
- an object containing `rules: []`
|
|
351
|
+
How hierarchies are used:
|
|
284
352
|
|
|
285
|
-
|
|
353
|
+
| Behaviour | Hierarchies used |
|
|
354
|
+
|---|---|
|
|
355
|
+
| Layering, parent-type, skip-level and orphan checks | Each hierarchy, independently. A hierarchy edge whose parent belongs to another hierarchy is an invalid parent. |
|
|
356
|
+
| Relationships | Connect types across hierarchies, as before |
|
|
357
|
+
| `space_on_a_page` parsing, hierarchy embedding, `template-sync` | Main hierarchy |
|
|
358
|
+
| `show`, `diagram`, `render` | Main hierarchy by default; `--hierarchy <name>` selects another |
|
|
359
|
+
| `resolvedParents` | Hierarchy edges carry the `hierarchy` name |
|
|
286
360
|
|
|
287
361
|
### Override example
|
|
288
362
|
|
|
@@ -295,30 +369,56 @@ Imported rules are normalized into one executable flat list before validation.
|
|
|
295
369
|
"override": true,
|
|
296
370
|
"category": "workflow",
|
|
297
371
|
"description": "Require exactly one active outcome",
|
|
298
|
-
"
|
|
299
|
-
"
|
|
372
|
+
"global": true,
|
|
373
|
+
"expression": "$count(nodes[resolvedType='outcome' and status='active']) = 1"
|
|
300
374
|
}
|
|
301
375
|
]
|
|
302
376
|
}
|
|
303
377
|
}
|
|
304
378
|
```
|
|
305
379
|
|
|
380
|
+
## Schema `$id` namespaces
|
|
381
|
+
|
|
382
|
+
Every schema `$id` uses the `sctx://` scheme. The shape of the `$id` says where the schema comes from:
|
|
383
|
+
|
|
384
|
+
| `$id` shape | Source | Example |
|
|
385
|
+
|---|---|---|
|
|
386
|
+
| `sctx://core/<name>` | Bundled with structured-context | `sctx://core/_sctx_base` |
|
|
387
|
+
| `sctx://<plugin>/<name>` | Contributed by a plugin (its short name, without `sctx-`) | `sctx://wardley-mapping/_wardley` |
|
|
388
|
+
| `sctx://<name>` | Local to a space's schema directory — a single name, no path | `sctx://team` |
|
|
389
|
+
|
|
390
|
+
- Two schemas loaded for the same space may not share an `$id`; a collision is an error naming both sources.
|
|
391
|
+
- `core` is reserved: no plugin may use it as its namespace.
|
|
392
|
+
- **Legacy bundled ids:** before 1.0, bundled schemas used `sctx://<name>` (e.g. `sctx://_sctx_base`, `sctx://strategy_general`). References to those ids in `$ref` and `$metadata.imports` still resolve to their `sctx://core/` equivalents with a deprecation warning, and local schemas may not use them as their own `$id`. The aliases will be removed in 1.0.
|
|
393
|
+
|
|
306
394
|
## Partials and `$ref`
|
|
307
395
|
|
|
308
396
|
- Files starting with `_` are auto-loaded partials.
|
|
309
|
-
-
|
|
310
|
-
-
|
|
397
|
+
- Bundled partials, local schema-directory partials, and partials from loaded plugins are all registered.
|
|
398
|
+
- `$id` values follow the [namespace rules](#schema-id-namespaces) and must not collide across bundled, plugin and local schemas.
|
|
311
399
|
- `$ref` resolution is transitive across files.
|
|
312
|
-
- Partials with no `$metadata` should prefer `$schema: "
|
|
313
|
-
- **Bundled partials as entity libraries**: `_sctx_base.json`, `_strategy_general.json`, `_knowledge_wiki.json`, and `_ost_strict.json` provide reusable entity definitions and metadata. Composing schemas can reference
|
|
314
|
-
- **Partials can carry metadata**: Partials may include `$metadata` (hierarchy, aliases, relationships, rules).
|
|
400
|
+
- Partials with no `$metadata` should prefer `$schema: "https://json-schema.org/draft/2020-12/schema"` so they validate standalone as plain JSON Schema fragments.
|
|
401
|
+
- **Bundled partials as entity libraries**: `_sctx_base.json`, `_strategy_general.json`, `_knowledge_wiki.json`, `_okf.json`, and `_ost_strict.json` provide reusable entity definitions and metadata. Composing schemas can reference their entity types via `$ref` rather than redefining them.
|
|
402
|
+
- **Partials can carry metadata**: Partials may include `$metadata` (hierarchy, aliases, relationships, rules). A schema gets it only by listing the partial in `$metadata.imports`; `$ref` alone brings none.
|
|
403
|
+
|
|
404
|
+
## Plugin-contributed schemas
|
|
405
|
+
|
|
406
|
+
Plugins contribute schemas and partials by standard directory convention: placing schema files in `<pluginRoot>/schemas/` (or declaring `"sctx": { "schemas": "./path" }` in `package.json`).
|
|
407
|
+
|
|
408
|
+
Because schemas are resolved statically by convention from the filesystem, structured-context does not need to execute plugin JavaScript code during schema validation, context creation, or schema inspection.
|
|
409
|
+
|
|
410
|
+
When a space uses a plugin schema:
|
|
411
|
+
- **Registry registration**: All partials (`_*`) in the plugin's `schemas/` directory are automatically indexed in the schema registry.
|
|
412
|
+
- **Namespace conventions**: Schemas contributed by a plugin must use `sctx://<pluginName>/...` for their `$id` (e.g. `sctx://wardley-mapping/_wardley`), where the prefix is the plugin's short name (without the `sctx-` prefix). See [Schema `$id` namespaces](#schema-id-namespaces).
|
|
413
|
+
- **Collision protection**: If two plugins register schemas with the same `$id`, or a plugin or local schema collides with a bundled schema, schema loading throws an error.
|
|
414
|
+
- **Imports and $ref**: Plugin schemas can `$ref` or `$metadata.imports` bundled schemas (e.g. `sctx://core/_sctx_base`) as well as other partials within their own namespace. Schema composition rules from #122 apply.
|
|
315
415
|
|
|
316
416
|
## Editor expectations
|
|
317
417
|
|
|
318
|
-
Use the shipped metaschema URL in `$schema` for best cross-tool behavior.
|
|
418
|
+
Use the shipped metaschema URL in `$schema` for best cross-tool behavior; pin a `<version>` URL if you need the dialect to stay fixed.
|
|
319
419
|
|
|
320
420
|
Notes:
|
|
321
|
-
-
|
|
421
|
+
- `sctx://` `$id`s are resolved by the CLI registry (see [Schema `$id` namespaces](#schema-id-namespaces)).
|
|
322
422
|
- Some generic editors may not resolve custom URI schemes for `$ref`; CLI behavior is authoritative.
|
|
323
423
|
- Do not rely on editor-only mappings for runtime correctness.
|
|
324
424
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "structured-context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.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",
|
|
@@ -25,47 +25,53 @@
|
|
|
25
25
|
"./types": {
|
|
26
26
|
"types": "./dist/types.d.ts",
|
|
27
27
|
"default": "./dist/types.js"
|
|
28
|
+
},
|
|
29
|
+
"./testing": {
|
|
30
|
+
"types": "./dist/testing.d.ts",
|
|
31
|
+
"default": "./dist/testing.js"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"scripts": {
|
|
31
35
|
"clean": "rm -rf dist",
|
|
32
36
|
"generate:schema-meta": "bun run scripts/generate-schema-meta.ts",
|
|
33
37
|
"typecheck": "tsc --noEmit",
|
|
34
|
-
"build": "bun run clean && bun run generate:schema-meta && tsc -p tsconfig.build.json && cp -r schemas dist/ && chmod +x dist/index.js",
|
|
38
|
+
"build": "bun run clean && bun run generate:schema-meta && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && cp -r schemas dist/ && chmod +x dist/index.js",
|
|
35
39
|
"prepublishOnly": "bun run build",
|
|
36
40
|
"validate": "bun run src/index.ts validate",
|
|
37
41
|
"diagram": "bun run src/index.ts diagram",
|
|
38
42
|
"test": "bun test tests/",
|
|
39
43
|
"test:smoke": "bun test smoke/",
|
|
44
|
+
"test:judge": "SCTX_LIVE_JUDGE_TESTS=1 bun test tests/judge/live.test.ts",
|
|
45
|
+
"test:models": "SCTX_MODEL_VALIDATION=1 bun test tests/judge/model-validation.test.ts",
|
|
40
46
|
"test:hook": "bun test hook-test/unit/",
|
|
41
47
|
"test:hook:e2e": "bun test hook-test/hooks.test.ts",
|
|
42
48
|
"test:all": "bun test",
|
|
43
49
|
"lint": "biome check",
|
|
44
50
|
"lint:fix": "biome check --write",
|
|
45
51
|
"preversion": "bun run generate:schema-meta && bun run lint:fix && bun run test",
|
|
46
|
-
"version": "git add -A",
|
|
52
|
+
"version": "bun run generate:schema-meta --release && git add -A",
|
|
47
53
|
"postversion": "git push --follow-tags"
|
|
48
54
|
},
|
|
49
55
|
"devDependencies": {
|
|
50
|
-
"@anthropic-ai/claude-agent-sdk": "^0.
|
|
51
|
-
"@biomejs/biome": "^2.
|
|
56
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.191",
|
|
57
|
+
"@biomejs/biome": "^2.5.15",
|
|
52
58
|
"@types/bun": "latest",
|
|
53
|
-
"@types/js-yaml": "^4.0.9",
|
|
54
59
|
"json-schema-to-ts": "^3.1.1",
|
|
55
|
-
"lefthook": "^2.1.
|
|
60
|
+
"lefthook": "^2.1.9",
|
|
61
|
+
"tsc-alias": "^1.9.1"
|
|
56
62
|
},
|
|
57
63
|
"peerDependencies": {
|
|
58
64
|
"typescript": "^5"
|
|
59
65
|
},
|
|
60
66
|
"dependencies": {
|
|
61
|
-
"ajv": "^8.
|
|
67
|
+
"ajv": "^8.20.0",
|
|
62
68
|
"chokidar": "^5.0.0",
|
|
63
|
-
"commander": "^
|
|
69
|
+
"commander": "^15.0.0",
|
|
64
70
|
"fast-glob": "^3.3.3",
|
|
65
71
|
"gray-matter": "^4.0.3",
|
|
66
|
-
"js-yaml": "^4.
|
|
72
|
+
"js-yaml": "^5.4.3",
|
|
67
73
|
"json5": "^2.2.3",
|
|
68
|
-
"jsonata": "^2.1
|
|
74
|
+
"jsonata": "^2.2.1",
|
|
69
75
|
"mdast-util-to-string": "^4.0.0",
|
|
70
76
|
"remark-gfm": "^4.0.1",
|
|
71
77
|
"remark-parse": "^11.0.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/_structured_context_schema_meta.json",
|
|
3
|
-
"$id": "sctx://_knowledge_wiki",
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/latest/_structured_context_schema_meta.json",
|
|
3
|
+
"$id": "sctx://core/_knowledge_wiki",
|
|
4
4
|
// Shared entity definitions for knowledge wiki schemas.
|
|
5
5
|
// Provides aliases, relationships, rules, and entity type $defs.
|
|
6
6
|
// This partial has no hierarchy — wiki entities are flat with no required parent links.
|
|
@@ -50,14 +50,14 @@
|
|
|
50
50
|
"category": "coherence",
|
|
51
51
|
"description": "Syntheses should reference at least one contributing source in their sources array",
|
|
52
52
|
"type": "synthesis",
|
|
53
|
-
"
|
|
53
|
+
"expression": "$exists(current.sources) and $count(current.sources) >= 1"
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
"id": "concept-has-summary",
|
|
57
57
|
"category": "best-practice",
|
|
58
58
|
"description": "Concept pages should have a short summary for index discoverability",
|
|
59
59
|
"type": "concept",
|
|
60
|
-
"
|
|
60
|
+
"expression": "$exists(current.summary) and $length(current.summary) > 0"
|
|
61
61
|
}
|
|
62
62
|
]
|
|
63
63
|
},
|
|
@@ -65,18 +65,18 @@
|
|
|
65
65
|
"source": {
|
|
66
66
|
"type": "object",
|
|
67
67
|
"description": "A processed summary of a raw source (article, paper, book, video, thread, podcast, etc.). Captures key information from the source in structured form with provenance.",
|
|
68
|
-
"allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
|
|
68
|
+
"allOf": [{ "$ref": "sctx://core/_sctx_base#/$defs/baseNodeProps" }],
|
|
69
69
|
"properties": {
|
|
70
70
|
"type": { "const": "source" },
|
|
71
71
|
"summary": {
|
|
72
|
-
"$ref": "sctx://_sctx_base#/$defs/summary"
|
|
72
|
+
"$ref": "sctx://core/_sctx_base#/$defs/summary"
|
|
73
73
|
},
|
|
74
74
|
"url": {
|
|
75
75
|
"type": "string",
|
|
76
76
|
"description": "URL of the original source"
|
|
77
77
|
},
|
|
78
78
|
"local_copy": {
|
|
79
|
-
"$ref": "sctx://_sctx_base#/$defs/wikilink",
|
|
79
|
+
"$ref": "sctx://core/_sctx_base#/$defs/wikilink",
|
|
80
80
|
"description": "Wikilink to a local copy of the source (e.g. a saved PDF or clipped note)"
|
|
81
81
|
},
|
|
82
82
|
"author": {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
},
|
|
90
90
|
"published_date": {
|
|
91
91
|
"type": "string",
|
|
92
|
-
"format": "date",
|
|
92
|
+
"format": "date-or-date-time",
|
|
93
93
|
"description": "Original publication date"
|
|
94
94
|
},
|
|
95
95
|
"source_type": {
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
"sources": {
|
|
100
100
|
"type": "array",
|
|
101
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
101
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
102
102
|
"description": "Wikilinks to other source pages that this one references or extends"
|
|
103
103
|
}
|
|
104
104
|
},
|
|
@@ -117,20 +117,20 @@
|
|
|
117
117
|
"concept": {
|
|
118
118
|
"type": "object",
|
|
119
119
|
"description": "A concept page — defines and frames a specific idea, mechanism, or domain term. May draw from multiple sources. The building blocks of the wiki's knowledge graph.",
|
|
120
|
-
"allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
|
|
120
|
+
"allOf": [{ "$ref": "sctx://core/_sctx_base#/$defs/baseNodeProps" }],
|
|
121
121
|
"properties": {
|
|
122
122
|
"type": { "const": "concept" },
|
|
123
123
|
"summary": {
|
|
124
|
-
"$ref": "sctx://_sctx_base#/$defs/summary"
|
|
124
|
+
"$ref": "sctx://core/_sctx_base#/$defs/summary"
|
|
125
125
|
},
|
|
126
126
|
"sources": {
|
|
127
127
|
"type": "array",
|
|
128
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
128
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
129
129
|
"description": "Wikilinks to source pages that contributed to this concept"
|
|
130
130
|
},
|
|
131
131
|
"related": {
|
|
132
132
|
"type": "array",
|
|
133
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
133
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
134
134
|
"description": "Wikilinks to related concept or synthesis pages"
|
|
135
135
|
}
|
|
136
136
|
},
|
|
@@ -147,20 +147,20 @@
|
|
|
147
147
|
"entity": {
|
|
148
148
|
"type": "object",
|
|
149
149
|
"description": "A concrete entity — a person, organisation, product, model, or other named thing. The building blocks of the wiki's knowledge graph alongside concepts. Entities are distinct from concepts: a concept frames an idea or mechanism; an entity is a specific, identifiable thing in the world.",
|
|
150
|
-
"allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
|
|
150
|
+
"allOf": [{ "$ref": "sctx://core/_sctx_base#/$defs/baseNodeProps" }],
|
|
151
151
|
"properties": {
|
|
152
152
|
"type": { "const": "entity" },
|
|
153
153
|
"summary": {
|
|
154
|
-
"$ref": "sctx://_sctx_base#/$defs/summary"
|
|
154
|
+
"$ref": "sctx://core/_sctx_base#/$defs/summary"
|
|
155
155
|
},
|
|
156
156
|
"sources": {
|
|
157
157
|
"type": "array",
|
|
158
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
158
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
159
159
|
"description": "Wikilinks to source pages that contributed to this entity page"
|
|
160
160
|
},
|
|
161
161
|
"related": {
|
|
162
162
|
"type": "array",
|
|
163
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
163
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
164
164
|
"description": "Wikilinks to related entity, concept, or synthesis pages"
|
|
165
165
|
}
|
|
166
166
|
},
|
|
@@ -177,20 +177,20 @@
|
|
|
177
177
|
"synthesis": {
|
|
178
178
|
"type": "object",
|
|
179
179
|
"description": "A synthesis page — connects multiple concepts and sources into a coherent model, framework, or thesis. The highest-value pages in a knowledge wiki. Must reference contributing sources.",
|
|
180
|
-
"allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
|
|
180
|
+
"allOf": [{ "$ref": "sctx://core/_sctx_base#/$defs/baseNodeProps" }],
|
|
181
181
|
"properties": {
|
|
182
182
|
"type": { "const": "synthesis" },
|
|
183
183
|
"summary": {
|
|
184
|
-
"$ref": "sctx://_sctx_base#/$defs/summary"
|
|
184
|
+
"$ref": "sctx://core/_sctx_base#/$defs/summary"
|
|
185
185
|
},
|
|
186
186
|
"sources": {
|
|
187
187
|
"type": "array",
|
|
188
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
188
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
189
189
|
"description": "Wikilinks to source pages this synthesis draws from"
|
|
190
190
|
},
|
|
191
191
|
"concepts": {
|
|
192
192
|
"type": "array",
|
|
193
|
-
"items": { "$ref": "sctx://_sctx_base#/$defs/wikilink" },
|
|
193
|
+
"items": { "$ref": "sctx://core/_sctx_base#/$defs/wikilink" },
|
|
194
194
|
"description": "Wikilinks to concept pages this synthesis connects"
|
|
195
195
|
}
|
|
196
196
|
},
|
|
@@ -208,12 +208,12 @@
|
|
|
208
208
|
"note": {
|
|
209
209
|
"type": "object",
|
|
210
210
|
"description": "Personal notes, journal entries, talk notes, or rough thoughts not drawn from an external URL.",
|
|
211
|
-
"allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
|
|
211
|
+
"allOf": [{ "$ref": "sctx://core/_sctx_base#/$defs/baseNodeProps" }],
|
|
212
212
|
"properties": {
|
|
213
213
|
"type": { "const": "note" },
|
|
214
214
|
"date": {
|
|
215
215
|
"type": "string",
|
|
216
|
-
"format": "date",
|
|
216
|
+
"format": "date-or-date-time",
|
|
217
217
|
"description": "Date this entry was created or relates to"
|
|
218
218
|
}
|
|
219
219
|
},
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
"index": {
|
|
231
231
|
"type": "object",
|
|
232
232
|
"description": "The wiki index — a catalog of all pages with links, summaries, and metadata. Updated by the agent on ingest. Used as the primary navigation entry point.",
|
|
233
|
-
"allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
|
|
233
|
+
"allOf": [{ "$ref": "sctx://core/_sctx_base#/$defs/baseNodeProps" }],
|
|
234
234
|
"properties": {
|
|
235
235
|
"type": { "const": "index" }
|
|
236
236
|
},
|