structured-context 0.9.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 (112) hide show
  1. package/README.md +348 -0
  2. package/dist/commands/diagram.d.ts +5 -0
  3. package/dist/commands/diagram.js +12 -0
  4. package/dist/commands/docs.d.ts +1 -0
  5. package/dist/commands/docs.js +67 -0
  6. package/dist/commands/dump.d.ts +2 -0
  7. package/dist/commands/dump.js +6 -0
  8. package/dist/commands/plugins.d.ts +1 -0
  9. package/dist/commands/plugins.js +23 -0
  10. package/dist/commands/render.d.ts +6 -0
  11. package/dist/commands/render.js +35 -0
  12. package/dist/commands/schemas.d.ts +6 -0
  13. package/dist/commands/schemas.js +268 -0
  14. package/dist/commands/show.d.ts +4 -0
  15. package/dist/commands/show.js +7 -0
  16. package/dist/commands/spaces.d.ts +1 -0
  17. package/dist/commands/spaces.js +36 -0
  18. package/dist/commands/template-sync.d.ts +3 -0
  19. package/dist/commands/template-sync.js +13 -0
  20. package/dist/commands/validate-file.d.ts +28 -0
  21. package/dist/commands/validate-file.js +133 -0
  22. package/dist/commands/validate.d.ts +16 -0
  23. package/dist/commands/validate.js +349 -0
  24. package/dist/config.d.ts +38 -0
  25. package/dist/config.js +179 -0
  26. package/dist/constants.d.ts +6 -0
  27. package/dist/constants.js +6 -0
  28. package/dist/filter/augment-nodes.d.ts +23 -0
  29. package/dist/filter/augment-nodes.js +95 -0
  30. package/dist/filter/expand-include.d.ts +62 -0
  31. package/dist/filter/expand-include.js +181 -0
  32. package/dist/filter/filter-nodes.d.ts +21 -0
  33. package/dist/filter/filter-nodes.js +73 -0
  34. package/dist/filter/parse-expression.d.ts +20 -0
  35. package/dist/filter/parse-expression.js +60 -0
  36. package/dist/index.d.ts +3 -0
  37. package/dist/index.js +161 -0
  38. package/dist/integrations/miro/cache.d.ts +21 -0
  39. package/dist/integrations/miro/cache.js +55 -0
  40. package/dist/integrations/miro/client.d.ts +99 -0
  41. package/dist/integrations/miro/client.js +118 -0
  42. package/dist/integrations/miro/layout.d.ts +28 -0
  43. package/dist/integrations/miro/layout.js +72 -0
  44. package/dist/integrations/miro/styles.d.ts +11 -0
  45. package/dist/integrations/miro/styles.js +65 -0
  46. package/dist/integrations/miro/sync.d.ts +8 -0
  47. package/dist/integrations/miro/sync.js +347 -0
  48. package/dist/plugin-api.d.ts +12 -0
  49. package/dist/plugin-api.js +7 -0
  50. package/dist/plugins/index.d.ts +3 -0
  51. package/dist/plugins/index.js +3 -0
  52. package/dist/plugins/loader.d.ts +21 -0
  53. package/dist/plugins/loader.js +104 -0
  54. package/dist/plugins/markdown/index.d.ts +48 -0
  55. package/dist/plugins/markdown/index.js +51 -0
  56. package/dist/plugins/markdown/parse-embedded.d.ts +90 -0
  57. package/dist/plugins/markdown/parse-embedded.js +663 -0
  58. package/dist/plugins/markdown/read-space.d.ts +7 -0
  59. package/dist/plugins/markdown/read-space.js +89 -0
  60. package/dist/plugins/markdown/render-bullets.d.ts +2 -0
  61. package/dist/plugins/markdown/render-bullets.js +42 -0
  62. package/dist/plugins/markdown/render-mermaid.d.ts +2 -0
  63. package/dist/plugins/markdown/render-mermaid.js +57 -0
  64. package/dist/plugins/markdown/template-sync.d.ts +16 -0
  65. package/dist/plugins/markdown/template-sync.js +294 -0
  66. package/dist/plugins/markdown/util.d.ts +19 -0
  67. package/dist/plugins/markdown/util.js +80 -0
  68. package/dist/plugins/util.d.ts +60 -0
  69. package/dist/plugins/util.js +7 -0
  70. package/dist/read/read-space.d.ts +2 -0
  71. package/dist/read/read-space.js +22 -0
  72. package/dist/read/resolve-graph-edges.d.ts +11 -0
  73. package/dist/read/resolve-graph-edges.js +201 -0
  74. package/dist/read/wikilink-utils.d.ts +16 -0
  75. package/dist/read/wikilink-utils.js +38 -0
  76. package/dist/render/registry.d.ts +13 -0
  77. package/dist/render/registry.js +22 -0
  78. package/dist/render/render.d.ts +4 -0
  79. package/dist/render/render.js +28 -0
  80. package/dist/schema/evaluate-rule.d.ts +30 -0
  81. package/dist/schema/evaluate-rule.js +82 -0
  82. package/dist/schema/metadata-contract.d.ts +538 -0
  83. package/dist/schema/metadata-contract.js +115 -0
  84. package/dist/schema/schema-refs.d.ts +22 -0
  85. package/dist/schema/schema-refs.js +168 -0
  86. package/dist/schema/schema.d.ts +27 -0
  87. package/dist/schema/schema.js +378 -0
  88. package/dist/schema/validate-graph.d.ts +24 -0
  89. package/dist/schema/validate-graph.js +141 -0
  90. package/dist/schema/validate-rules.d.ts +10 -0
  91. package/dist/schema/validate-rules.js +51 -0
  92. package/dist/schemas/_ost_strict.json +81 -0
  93. package/dist/schemas/_sctx_base.json +72 -0
  94. package/dist/schemas/general.json +261 -0
  95. package/dist/schemas/generated/_structured_context_schema_meta.json +191 -0
  96. package/dist/schemas/knowledge_wiki.json +206 -0
  97. package/dist/schemas/strict_ost.json +97 -0
  98. package/dist/space-graph.d.ts +28 -0
  99. package/dist/space-graph.js +82 -0
  100. package/dist/types.d.ts +145 -0
  101. package/dist/types.js +0 -0
  102. package/docs/concepts.md +391 -0
  103. package/docs/config.md +140 -0
  104. package/docs/rules.md +120 -0
  105. package/docs/schemas.md +340 -0
  106. package/package.json +69 -0
  107. package/schemas/_ost_strict.json +81 -0
  108. package/schemas/_sctx_base.json +72 -0
  109. package/schemas/general.json +261 -0
  110. package/schemas/generated/_structured_context_schema_meta.json +191 -0
  111. package/schemas/knowledge_wiki.json +206 -0
  112. package/schemas/strict_ost.json +97 -0
@@ -0,0 +1,141 @@
1
+ import { resolveNodeType } from '../schema/schema';
2
+ /**
3
+ * Validate graph structure using pre-collected unresolved refs from resolveGraphEdges.
4
+ * Assumes resolveGraphEdges has already been called to populate node.resolvedParents.
5
+ */
6
+ export function validateGraph(nodes, metadata, unresolvedRefs = []) {
7
+ const refErrors = unresolvedRefs.map((u) => ({ file: u.label, parent: u.ref, error: u.message }));
8
+ const violations = validateHierarchyStructure(nodes, metadata);
9
+ return { violations, refErrors };
10
+ }
11
+ /**
12
+ * Validate that resolved parents follow hierarchy level rules and relationship type constraints.
13
+ *
14
+ * For hierarchy edges (fieldOn:'child', source:'hierarchy'): validates level ordering.
15
+ * For relationship edges (fieldOn:'child', source:'relationship'): validates parent type.
16
+ * For fieldOn:'parent' edges: validates child type, violation attributed to the field-owner node.
17
+ *
18
+ * Assumes resolveGraphEdges has already been called to populate node.resolvedParents.
19
+ */
20
+ export function validateHierarchyStructure(nodes, metadata) {
21
+ const violations = [];
22
+ const levels = metadata.hierarchy?.levels ?? [];
23
+ const relationships = metadata.relationships ?? [];
24
+ const allowSkipLevels = metadata.hierarchy?.allowSkipLevels ?? false;
25
+ const typeAliases = metadata.typeAliases;
26
+ const hierarchy = levels.map((level) => resolveNodeType(level.type, typeAliases));
27
+ // Build type rules: (ownerType, field) → set of valid target types.
28
+ // For fieldOn:'child': owner=childType, target=parentType.
29
+ // For fieldOn:'parent': owner=parentType (field owner), target=childType.
30
+ const typeRules = new Map();
31
+ function addTypeRule(ownerType, field, targetType) {
32
+ const owner = resolveNodeType(ownerType, typeAliases);
33
+ const target = resolveNodeType(targetType, typeAliases);
34
+ if (!typeRules.has(owner))
35
+ typeRules.set(owner, new Map());
36
+ const fieldMap = typeRules.get(owner);
37
+ if (!fieldMap.has(field))
38
+ fieldMap.set(field, new Set());
39
+ fieldMap.get(field).add(target);
40
+ }
41
+ for (let i = 1; i < levels.length; i++) {
42
+ const level = levels[i];
43
+ const parentLevel = levels[i - 1];
44
+ if (level.fieldOn === 'parent') {
45
+ addTypeRule(parentLevel.type, level.field, level.type);
46
+ if (level.selfRef)
47
+ addTypeRule(level.type, level.field, level.type);
48
+ }
49
+ else {
50
+ addTypeRule(level.type, level.field, parentLevel.type);
51
+ if (level.selfRef)
52
+ addTypeRule(level.type, level.field, level.type);
53
+ }
54
+ }
55
+ for (const rel of relationships) {
56
+ if (rel.fieldOn === 'parent') {
57
+ addTypeRule(rel.parent, rel.field, rel.type);
58
+ }
59
+ else {
60
+ addTypeRule(rel.type, rel.field, rel.parent);
61
+ }
62
+ }
63
+ const nodeIndex = new Map();
64
+ for (const node of nodes) {
65
+ const title = node.title;
66
+ if (title)
67
+ nodeIndex.set(title, node);
68
+ }
69
+ for (const node of nodes) {
70
+ const nodeType = node.resolvedType;
71
+ const nodeTitle = node.title;
72
+ for (const parentRef of node.resolvedParents) {
73
+ const parentNode = nodeIndex.get(parentRef.title);
74
+ if (!parentNode)
75
+ continue;
76
+ const parentType = parentNode.resolvedType;
77
+ const parentTitle = parentRef.title;
78
+ if (parentRef.fieldOn === 'parent') {
79
+ // Field is on the parent node; validate that this node's type matches the expected child type.
80
+ // Violation is attributed to the field-owner (parent) node.
81
+ const allowedChildTypes = typeRules.get(parentType)?.get(parentRef.field);
82
+ if (allowedChildTypes && !allowedChildTypes.has(nodeType)) {
83
+ const expected = [...allowedChildTypes].join(' or ');
84
+ violations.push({
85
+ file: parentNode.label,
86
+ nodeType: parentType,
87
+ nodeTitle: parentTitle,
88
+ parentType: nodeType,
89
+ parentTitle: nodeTitle,
90
+ description: `Invalid relationship: ${parentType} "${parentTitle}" has "${nodeTitle}" in field "${parentRef.field}" which is of type ${nodeType}, expected ${expected}`,
91
+ });
92
+ }
93
+ }
94
+ else if (parentRef.source === 'relationship') {
95
+ // Relationship edge (fieldOn:'child'): validate parent type matches relationship definition.
96
+ const allowedTypes = typeRules.get(nodeType)?.get(parentRef.field);
97
+ if (allowedTypes && !allowedTypes.has(parentType)) {
98
+ const expected = [...allowedTypes].join(' or ');
99
+ violations.push({
100
+ file: node.label,
101
+ nodeType,
102
+ nodeTitle,
103
+ parentType,
104
+ parentTitle,
105
+ description: `Invalid relationship: ${nodeType} "${nodeTitle}" has "${parentTitle}" in field "${parentRef.field}" which is of type ${parentType}, expected ${expected}`,
106
+ });
107
+ }
108
+ }
109
+ else {
110
+ // Hierarchy edge (fieldOn:'child', source:'hierarchy'): validate level ordering.
111
+ const typeIndex = hierarchy.indexOf(nodeType);
112
+ const parentIndex = hierarchy.indexOf(parentType);
113
+ if (typeIndex === -1 || parentIndex === -1)
114
+ continue;
115
+ const level = levels[typeIndex];
116
+ const canSelfRef = level.selfRef || level.selfRefField !== undefined;
117
+ let isValidHierarchy = false;
118
+ if (parentIndex === typeIndex - 1) {
119
+ isValidHierarchy = true;
120
+ }
121
+ else if (canSelfRef && parentIndex === typeIndex) {
122
+ isValidHierarchy = true;
123
+ }
124
+ else if (allowSkipLevels && parentIndex < typeIndex) {
125
+ isValidHierarchy = true;
126
+ }
127
+ if (!isValidHierarchy) {
128
+ violations.push({
129
+ file: node.label,
130
+ nodeType,
131
+ nodeTitle,
132
+ parentType,
133
+ parentTitle,
134
+ description: `Invalid parent: ${nodeType} "${nodeTitle}" cannot have ${parentType} "${parentTitle}" as parent`,
135
+ });
136
+ }
137
+ }
138
+ }
139
+ }
140
+ return violations;
141
+ }
@@ -0,0 +1,10 @@
1
+ import type { Rule, RuleViolation, SpaceNode } from '../types';
2
+ /**
3
+ * Validate nodes against rules metadata.
4
+ * Returns a list of rule violations found.
5
+ *
6
+ * @param nodes - All nodes in the space
7
+ * @param rules - Rules metadata list
8
+ * @returns Array of rule violations
9
+ */
10
+ export declare function validateRules(nodes: SpaceNode[], rules: Rule[]): Promise<RuleViolation[]>;
@@ -0,0 +1,51 @@
1
+ import { buildEvalContext, evaluateExpression } from './evaluate-rule';
2
+ /**
3
+ * Validate nodes against rules metadata.
4
+ * Returns a list of rule violations found.
5
+ *
6
+ * @param nodes - All nodes in the space
7
+ * @param rules - Rules metadata list
8
+ * @returns Array of rule violations
9
+ */
10
+ export async function validateRules(nodes, rules) {
11
+ const violations = [];
12
+ // Build node index for efficient lookups
13
+ const nodeIndex = new Map();
14
+ for (const node of nodes) {
15
+ const title = node.title;
16
+ if (title) {
17
+ nodeIndex.set(title, node);
18
+ }
19
+ }
20
+ // Evaluate each rule against applicable nodes
21
+ for (const rule of rules) {
22
+ if (rule.scope === 'global') {
23
+ // Global rules are evaluated once against the full node set.
24
+ // A sentinel node provides the evaluation context (nodes array is what matters).
25
+ const sentinel = nodes[0];
26
+ if (sentinel) {
27
+ const context = buildEvalContext(sentinel, nodes, nodeIndex);
28
+ const result = await evaluateExpression(rule.check, context);
29
+ if (result !== true) {
30
+ violations.push({ file: '', ruleId: rule.id, category: rule.category, description: rule.description });
31
+ }
32
+ }
33
+ }
34
+ else {
35
+ const targetNodes = rule.type ? nodes.filter((n) => n.resolvedType === rule.type) : nodes;
36
+ for (const node of targetNodes) {
37
+ const context = buildEvalContext(node, nodes, nodeIndex);
38
+ const result = await evaluateExpression(rule.check, context);
39
+ if (result !== true) {
40
+ violations.push({
41
+ file: node.label,
42
+ ruleId: rule.id,
43
+ category: rule.category,
44
+ description: rule.description,
45
+ });
46
+ }
47
+ }
48
+ }
49
+ }
50
+ return violations;
51
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/_structured_context_schema_meta.json",
3
+ "$id": "sctx://_ost_strict",
4
+ // Shared definitions for the strict OST (Opportunity Solution Tree) schema.
5
+ // This schema follows Teresa Torres' canonical 4-level structure as described in
6
+ // "Continuous Discovery Habits" (2021) and at producttalk.org.
7
+ "$metadata": {
8
+ "hierarchy": {
9
+ "levels": ["outcome", { "type": "opportunity", "selfRef": true }, "solution", "assumption_test"]
10
+ },
11
+ "rules": [
12
+ {
13
+ "id": "active-outcome-count",
14
+ "category": "workflow",
15
+ "description": "Only one outcome should be active at a time",
16
+ "scope": "global",
17
+ "check": "$count(nodes[resolvedType='outcome' and status='active']) <= 1"
18
+ },
19
+ {
20
+ "id": "active-opportunity-count",
21
+ "category": "workflow",
22
+ "description": "Only one target opportunity should be active at a time",
23
+ "scope": "global",
24
+ "check": "$count(nodes[resolvedType='opportunity' and status='active']) <= 1"
25
+ },
26
+ {
27
+ "id": "active-node-parent-active",
28
+ "category": "workflow",
29
+ "description": "An active node's parent should also be active",
30
+ "check": "current.status != 'active' or $exists(parent) = false or parent.status = 'active'"
31
+ },
32
+ {
33
+ "id": "solution-quantity",
34
+ "category": "best-practice",
35
+ "description": "Explore multiple candidate solutions (aim for at least three) for the target opportunity",
36
+ "type": "opportunity",
37
+ "check": "(current.status != 'exploring' and current.status != 'active') or $count(nodes[resolvedParentTitle=$$.current.title and resolvedType='solution']) >= 3"
38
+ }
39
+ ]
40
+ },
41
+ "$defs": {
42
+ "outcomeProps": {
43
+ "type": "object",
44
+ "description": "Properties for an Outcome node (product metric, not vision/mission)",
45
+ "properties": {
46
+ "metric": {
47
+ "type": "string",
48
+ "description": "The specific product metric to move (e.g., 'Increase % of first-time users who reach the aha moment')"
49
+ }
50
+ },
51
+ "required": ["metric"]
52
+ },
53
+ "opportunityProps": {
54
+ "type": "object",
55
+ "description": "Properties for an Opportunity, emphasizing research grounding",
56
+ "properties": {
57
+ "source": {
58
+ "type": "string",
59
+ "description": "Customer research source that grounded this opportunity (e.g., 'Interview with Jane, 2024-03-15')"
60
+ }
61
+ },
62
+ "required": ["source"]
63
+ },
64
+ "assumptionTestProps": {
65
+ "type": "object",
66
+ "description": "Properties for an Assumption Test (the fourth level of the OST)",
67
+ "properties": {
68
+ "assumption": {
69
+ "type": "string",
70
+ "description": "The specific belief being tested"
71
+ },
72
+ "category": {
73
+ "type": "string",
74
+ "enum": ["desirability", "viability", "feasibility", "usability", "ethical"],
75
+ "description": "Assumption type categories"
76
+ }
77
+ },
78
+ "required": ["assumption"]
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "sctx://_sctx_base",
4
+ "description": "Shared definitions for structured-context schemas",
5
+ "$defs": {
6
+ "title": {
7
+ "type": "string",
8
+ "description": "Title of the node"
9
+ },
10
+ "content": {
11
+ "type": "string",
12
+ "description": "Body content"
13
+ },
14
+ "summary": {
15
+ "type": "string",
16
+ "description": "Short summary"
17
+ },
18
+ "status": {
19
+ "type": "string",
20
+ "enum": ["identified", "wondering", "exploring", "active", "paused", "completed", "archived"]
21
+ },
22
+ "priority": {
23
+ "type": "string",
24
+ "enum": ["p1", "p2", "p3", "p4"]
25
+ },
26
+ "assessment": {
27
+ "type": "integer",
28
+ "minimum": 1,
29
+ "maximum": 5,
30
+ "description": "Assessment score from 1-5"
31
+ },
32
+ "wikilink": {
33
+ "type": "string",
34
+ "pattern": "^\\[\\[.+\\]\\]$",
35
+ "description": "An Obsidian wikilink, e.g. [[Parent Node]]"
36
+ },
37
+ "baseNodeProps": {
38
+ "type": "object",
39
+ "properties": {
40
+ "title": { "$ref": "#/$defs/title" },
41
+ "content": { "$ref": "#/$defs/content" },
42
+ "tags": {
43
+ "type": "array",
44
+ "items": { "type": "string" },
45
+ "description": "Categorization tags"
46
+ }
47
+ },
48
+ "required": ["title"]
49
+ },
50
+ "ostEntityProps": {
51
+ "type": "object",
52
+ "properties": {
53
+ "status": { "$ref": "#/$defs/status" },
54
+ "summary": { "$ref": "#/$defs/summary" },
55
+ "status_tweet": {
56
+ "type": "string",
57
+ "description": "Succinct free-text status summary"
58
+ }
59
+ },
60
+ "required": ["status"]
61
+ },
62
+ "parentNodeProps": {
63
+ "type": "object",
64
+ "properties": {
65
+ "parent": {
66
+ "$ref": "#/$defs/wikilink",
67
+ "description": "Parent node"
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,261 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/mindsocket/structured-context/main/schemas/generated/_structured_context_schema_meta.json",
3
+ "$id": "sctx://general",
4
+ "title": "Strategy and opportunity ladder",
5
+ "description": "Validates frontmatter for space node files",
6
+ "$metadata": {
7
+ "hierarchy": {
8
+ "levels": [
9
+ "vision",
10
+ "mission",
11
+ { "type": "goal", "selfRef": true, "matchers": ["Goals"] },
12
+ { "type": "opportunity", "selfRef": true, "matchers": ["Opportunities"] },
13
+ {
14
+ "type": "solution",
15
+ "selfRef": true,
16
+ "matchers": ["Solutions", "Potential solutions", "Solutions considered", "Possible solutions"]
17
+ },
18
+ "experiment"
19
+ ]
20
+ },
21
+ "aliases": {
22
+ "outcome": "goal",
23
+ "assumption_test": "experiment",
24
+ "test": "experiment"
25
+ },
26
+ "relationships": [
27
+ {
28
+ "parent": "opportunity",
29
+ "type": "problem_statement",
30
+ "templateFormat": "heading",
31
+ "matchers": ["Problem statement", "What problem are we solving?"],
32
+ "multiple": false
33
+ },
34
+ {
35
+ "parent": "opportunity",
36
+ "type": "assumption",
37
+ "templateFormat": "table",
38
+ "matchers": ["Assumptions", "^Assumptions?$"],
39
+ "embeddedTemplateFields": ["assumption", "status", "confidence"],
40
+ "multiple": true
41
+ }
42
+ ]
43
+ },
44
+ "oneOf": [
45
+ {
46
+ "type": "object",
47
+ "allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
48
+ "properties": {
49
+ "type": { "const": "dashboard" }
50
+ },
51
+ "required": ["type"],
52
+ "additionalProperties": true
53
+ },
54
+ {
55
+ "type": "object",
56
+ "allOf": [{ "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" }],
57
+ "properties": {
58
+ "type": { "enum": ["ost_on_a_page", "space_on_a_page"] }
59
+ },
60
+ "required": ["type"],
61
+ "additionalProperties": true
62
+ },
63
+ {
64
+ "type": "object",
65
+ "allOf": [
66
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
67
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
68
+ ],
69
+ "properties": {
70
+ "type": { "const": "vision" }
71
+ },
72
+ "required": ["type"],
73
+ "not": { "required": ["parent"] },
74
+ "additionalProperties": true,
75
+ "examples": [
76
+ {
77
+ "type": "vision",
78
+ "status": "active"
79
+ }
80
+ ]
81
+ },
82
+ {
83
+ "type": "object",
84
+ "allOf": [
85
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
86
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
87
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
88
+ ],
89
+ "properties": {
90
+ "type": { "const": "mission" }
91
+ },
92
+ "required": ["type"],
93
+ "additionalProperties": true,
94
+ "examples": [
95
+ {
96
+ "type": "mission",
97
+ "status": "active",
98
+ "parent": "[[Personal Vision]]"
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ "type": "object",
104
+ "allOf": [
105
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
106
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
107
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
108
+ ],
109
+ "properties": {
110
+ "type": { "enum": ["goal", "outcome"] },
111
+ "priority": { "$ref": "sctx://_sctx_base#/$defs/priority" }
112
+ },
113
+ "required": ["type"],
114
+ "additionalProperties": true,
115
+ "examples": [
116
+ {
117
+ "type": "goal",
118
+ "status": "active",
119
+ "parent": "[[My Mission (2026)]]",
120
+ "priority": "p2"
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ "type": "object",
126
+ "allOf": [
127
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
128
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
129
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
130
+ ],
131
+ "properties": {
132
+ "type": { "const": "opportunity" },
133
+ "priority": { "$ref": "sctx://_sctx_base#/$defs/priority" },
134
+ "impact": { "$ref": "sctx://_sctx_base#/$defs/assessment" },
135
+ "feasibility": { "$ref": "sctx://_sctx_base#/$defs/assessment" },
136
+ "resources": { "$ref": "sctx://_sctx_base#/$defs/assessment" },
137
+ "timeline": {
138
+ "type": "string",
139
+ "description": "Timeline estimate (e.g., S-M, M-L)"
140
+ },
141
+ "next_steps": {
142
+ "type": "string",
143
+ "description": "Next steps for this opportunity"
144
+ }
145
+ },
146
+ "required": ["type"],
147
+ "additionalProperties": true,
148
+ "examples": [
149
+ {
150
+ "type": "opportunity",
151
+ "status": "identified",
152
+ "parent": "[[Career Growth]]",
153
+ "priority": "p2"
154
+ }
155
+ ]
156
+ },
157
+ {
158
+ "type": "object",
159
+ "allOf": [
160
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
161
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
162
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
163
+ ],
164
+ "properties": {
165
+ "type": { "const": "solution" },
166
+ "priority": { "$ref": "sctx://_sctx_base#/$defs/priority" },
167
+ "impact": { "$ref": "sctx://_sctx_base#/$defs/assessment" },
168
+ "feasibility": { "$ref": "sctx://_sctx_base#/$defs/assessment" },
169
+ "resources": { "$ref": "sctx://_sctx_base#/$defs/assessment" },
170
+ "timeline": {
171
+ "type": "string",
172
+ "description": "Timeline estimate (e.g., S-M, M-L)"
173
+ },
174
+ "next_steps": {
175
+ "type": "string",
176
+ "description": "Next steps for this solution"
177
+ }
178
+ },
179
+ "required": ["type"],
180
+ "additionalProperties": true,
181
+ "examples": [
182
+ {
183
+ "type": "solution",
184
+ "status": "identified",
185
+ "parent": "[[Some Opportunity]]",
186
+ "priority": "p3"
187
+ }
188
+ ]
189
+ },
190
+ {
191
+ "type": "object",
192
+ "allOf": [
193
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
194
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
195
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
196
+ ],
197
+ "properties": {
198
+ "type": { "enum": ["experiment", "assumption_test", "test"] }
199
+ },
200
+ "required": ["type"],
201
+ "additionalProperties": true,
202
+ "examples": [
203
+ {
204
+ "type": "experiment",
205
+ "status": "exploring",
206
+ "parent": "[[Build a Side Project]]"
207
+ },
208
+ {
209
+ "type": "test",
210
+ "status": "active",
211
+ "parent": "[[Mobile App Solution]]"
212
+ }
213
+ ]
214
+ },
215
+ {
216
+ "type": "object",
217
+ "allOf": [
218
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
219
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
220
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
221
+ ],
222
+ "properties": {
223
+ "type": { "const": "assumption" },
224
+ "confidence": {
225
+ "type": "string",
226
+ "enum": ["low", "medium", "high"],
227
+ "description": "Confidence level in this assumption"
228
+ }
229
+ },
230
+ "required": ["type"],
231
+ "additionalProperties": true,
232
+ "examples": [
233
+ {
234
+ "type": "assumption",
235
+ "status": "identified",
236
+ "parent": "[[Some Opportunity]]",
237
+ "confidence": "medium"
238
+ }
239
+ ]
240
+ },
241
+ {
242
+ "type": "object",
243
+ "allOf": [
244
+ { "$ref": "sctx://_sctx_base#/$defs/baseNodeProps" },
245
+ { "$ref": "sctx://_sctx_base#/$defs/parentNodeProps" },
246
+ { "$ref": "sctx://_sctx_base#/$defs/ostEntityProps" }
247
+ ],
248
+ "properties": {
249
+ "type": { "const": "problem_statement" }
250
+ },
251
+ "required": ["type"],
252
+ "additionalProperties": true,
253
+ "examples": [
254
+ {
255
+ "type": "problem_statement",
256
+ "status": "identified"
257
+ }
258
+ ]
259
+ }
260
+ ]
261
+ }