@forwardimpact/schema 0.4.0 → 0.7.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/bin/fit-schema.js +2 -2
- package/examples/capabilities/business.yaml +27 -11
- package/examples/capabilities/delivery.yaml +65 -27
- package/examples/capabilities/people.yaml +1 -1
- package/examples/capabilities/reliability.yaml +85 -31
- package/examples/capabilities/scale.yaml +83 -31
- package/examples/framework.yaml +5 -1
- package/examples/questions/behaviours/outcome_ownership.yaml +226 -49
- package/examples/questions/behaviours/polymathic_knowledge.yaml +273 -45
- package/examples/questions/behaviours/precise_communication.yaml +246 -52
- package/examples/questions/behaviours/relentless_curiosity.yaml +246 -48
- package/examples/questions/behaviours/systems_thinking.yaml +236 -50
- package/examples/questions/capabilities/business.yaml +107 -0
- package/examples/questions/capabilities/delivery.yaml +104 -0
- package/examples/questions/capabilities/people.yaml +104 -0
- package/examples/questions/capabilities/reliability.yaml +103 -0
- package/examples/questions/capabilities/scale.yaml +103 -0
- package/examples/questions/skills/architecture_design.yaml +102 -51
- package/examples/questions/skills/cloud_platforms.yaml +90 -44
- package/examples/questions/skills/code_quality.yaml +86 -45
- package/examples/questions/skills/data_modeling.yaml +93 -43
- package/examples/questions/skills/devops.yaml +91 -44
- package/examples/questions/skills/full_stack_development.yaml +93 -45
- package/examples/questions/skills/sre_practices.yaml +92 -41
- package/examples/questions/skills/stakeholder_management.yaml +97 -46
- package/examples/questions/skills/team_collaboration.yaml +87 -40
- package/examples/questions/skills/technical_writing.yaml +89 -40
- package/examples/stages.yaml +52 -13
- package/package.json +9 -9
- package/schema/json/behaviour-questions.schema.json +53 -26
- package/schema/json/capability-questions.schema.json +95 -0
- package/schema/json/capability.schema.json +8 -7
- package/schema/json/framework.schema.json +13 -0
- package/schema/json/skill-questions.schema.json +34 -19
- package/schema/json/stages.schema.json +6 -6
- package/schema/rdf/behaviour-questions.ttl +39 -7
- package/schema/rdf/capability.ttl +15 -15
- package/schema/rdf/defs.ttl +3 -3
- package/schema/rdf/framework.ttl +38 -0
- package/schema/rdf/skill-questions.ttl +28 -1
- package/schema/rdf/stages.ttl +14 -14
- package/{lib → src}/levels.js +53 -101
- package/{lib → src}/loader.js +9 -5
- package/{lib → src}/modifiers.js +3 -3
- package/{lib → src}/validation.js +105 -79
- /package/{lib → src}/index-generator.js +0 -0
- /package/{lib → src}/index.js +0 -0
- /package/{lib → src}/schema-validation.js +0 -0
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"properties": {
|
|
15
15
|
"id": {
|
|
16
16
|
"type": "string",
|
|
17
|
-
"enum": ["specify", "plan", "code", "review", "deploy"],
|
|
17
|
+
"enum": ["specify", "plan", "onboard", "code", "review", "deploy"],
|
|
18
18
|
"description": "Stage identifier"
|
|
19
19
|
},
|
|
20
20
|
"name": {
|
|
@@ -47,16 +47,16 @@
|
|
|
47
47
|
"type": "string"
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
-
"
|
|
50
|
+
"readChecklist": {
|
|
51
51
|
"type": "array",
|
|
52
|
-
"description": "
|
|
52
|
+
"description": "Read-Then-Do Checklist: steps to follow in order during this stage",
|
|
53
53
|
"items": {
|
|
54
54
|
"type": "string"
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
|
-
"
|
|
57
|
+
"confirmChecklist": {
|
|
58
58
|
"type": "array",
|
|
59
|
-
"description": "
|
|
59
|
+
"description": "Do-Then-Confirm Checklist: items to verify before handing off to next stage",
|
|
60
60
|
"items": {
|
|
61
61
|
"type": "string"
|
|
62
62
|
}
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"properties": {
|
|
71
71
|
"targetStage": {
|
|
72
72
|
"type": "string",
|
|
73
|
-
"enum": ["specify", "plan", "code", "review", "deploy"],
|
|
73
|
+
"enum": ["specify", "plan", "onboard", "code", "review", "deploy"],
|
|
74
74
|
"description": "The stage to transition to"
|
|
75
75
|
},
|
|
76
76
|
"label": {
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
# =============================================================================
|
|
8
8
|
# Behaviour Questions Schema
|
|
9
9
|
# =============================================================================
|
|
10
|
-
#
|
|
10
|
+
# Stakeholder simulation interview questions for assessing behaviours,
|
|
11
|
+
# organized by role type (professional/management) and maturity level.
|
|
12
|
+
# Each question presents a realistic stakeholder scenario with simulation
|
|
13
|
+
# prompts to guide the interview panel.
|
|
11
14
|
# =============================================================================
|
|
12
15
|
|
|
13
16
|
# -----------------------------------------------------------------------------
|
|
@@ -26,6 +29,12 @@ fit:atMaturity a rdf:Property ;
|
|
|
26
29
|
rdfs:domain fit:Question ;
|
|
27
30
|
rdfs:range fit:BehaviourMaturity .
|
|
28
31
|
|
|
32
|
+
fit:simulationPrompts a rdf:Property ;
|
|
33
|
+
rdfs:label "simulationPrompts"@en ;
|
|
34
|
+
rdfs:comment "Guiding prompts to steer the stakeholder simulation and probe the candidate's behaviour"@en ;
|
|
35
|
+
rdfs:domain fit:Question ;
|
|
36
|
+
rdfs:range xsd:string .
|
|
37
|
+
|
|
29
38
|
# =============================================================================
|
|
30
39
|
# SHACL SHAPES
|
|
31
40
|
# =============================================================================
|
|
@@ -48,27 +57,42 @@ fit:BehaviourQuestionShape a sh:NodeShape ;
|
|
|
48
57
|
sh:property [
|
|
49
58
|
sh:path fit:text ;
|
|
50
59
|
sh:datatype xsd:string ;
|
|
51
|
-
sh:maxLength
|
|
60
|
+
sh:maxLength 300 ;
|
|
52
61
|
sh:minCount 1 ;
|
|
53
62
|
sh:maxCount 1 ;
|
|
54
63
|
sh:name "text" ;
|
|
55
|
-
sh:description "The
|
|
64
|
+
sh:description "The stakeholder scenario (under 300 characters)" ;
|
|
65
|
+
] ;
|
|
66
|
+
sh:property [
|
|
67
|
+
sh:path fit:context ;
|
|
68
|
+
sh:datatype xsd:string ;
|
|
69
|
+
sh:maxCount 1 ;
|
|
70
|
+
sh:name "context" ;
|
|
71
|
+
sh:description "Additional context to set up the simulation scenario" ;
|
|
72
|
+
] ;
|
|
73
|
+
sh:property [
|
|
74
|
+
sh:path fit:simulationPrompts ;
|
|
75
|
+
sh:datatype xsd:string ;
|
|
76
|
+
sh:minCount 2 ;
|
|
77
|
+
sh:maxCount 5 ;
|
|
78
|
+
sh:name "simulationPrompts" ;
|
|
79
|
+
sh:description "3-5 guiding prompts to steer the simulation" ;
|
|
56
80
|
] ;
|
|
57
81
|
sh:property [
|
|
58
82
|
sh:path fit:lookingFor ;
|
|
59
83
|
sh:datatype xsd:string ;
|
|
60
|
-
sh:minCount
|
|
84
|
+
sh:minCount 2 ;
|
|
61
85
|
sh:maxCount 4 ;
|
|
62
86
|
sh:name "lookingFor" ;
|
|
63
|
-
sh:description "2-4
|
|
87
|
+
sh:description "2-4 indicators of strong behavioural response" ;
|
|
64
88
|
] ;
|
|
65
89
|
sh:property [
|
|
66
90
|
sh:path fit:expectedDurationMinutes ;
|
|
67
91
|
sh:datatype xsd:integer ;
|
|
68
|
-
sh:minInclusive
|
|
92
|
+
sh:minInclusive 10 ;
|
|
69
93
|
sh:maxCount 1 ;
|
|
70
94
|
sh:name "expectedDurationMinutes" ;
|
|
71
|
-
sh:description "Expected duration in minutes" ;
|
|
95
|
+
sh:description "Expected duration in minutes (default: 20)" ;
|
|
72
96
|
] ;
|
|
73
97
|
sh:property [
|
|
74
98
|
sh:path fit:followUps ;
|
|
@@ -93,4 +117,12 @@ fit:BehaviourQuestionShape a sh:NodeShape ;
|
|
|
93
117
|
sh:maxCount 1 ;
|
|
94
118
|
sh:name "atMaturity" ;
|
|
95
119
|
sh:description "The behaviour maturity this question is for" ;
|
|
120
|
+
] ;
|
|
121
|
+
sh:property [
|
|
122
|
+
sh:path fit:forRoleType ;
|
|
123
|
+
sh:in ( fit:professional fit:management ) ;
|
|
124
|
+
sh:minCount 1 ;
|
|
125
|
+
sh:maxCount 1 ;
|
|
126
|
+
sh:name "forRoleType" ;
|
|
127
|
+
sh:description "The role type this question is for" ;
|
|
96
128
|
] .
|
|
@@ -153,14 +153,14 @@ fit:focus a rdf:Property ;
|
|
|
153
153
|
rdfs:comment "Primary focus for this stage"@en ;
|
|
154
154
|
rdfs:range xsd:string .
|
|
155
155
|
|
|
156
|
-
fit:
|
|
157
|
-
rdfs:label "
|
|
158
|
-
rdfs:comment "
|
|
156
|
+
fit:readChecklist a rdf:Property ;
|
|
157
|
+
rdfs:label "readChecklist"@en ;
|
|
158
|
+
rdfs:comment "Read-Then-Do Checklist: steps to follow in order during this stage"@en ;
|
|
159
159
|
rdfs:range xsd:string .
|
|
160
160
|
|
|
161
|
-
fit:
|
|
162
|
-
rdfs:label "
|
|
163
|
-
rdfs:comment "
|
|
161
|
+
fit:confirmChecklist a rdf:Property ;
|
|
162
|
+
rdfs:label "confirmChecklist"@en ;
|
|
163
|
+
rdfs:comment "Do-Then-Confirm Checklist: items to verify before moving to next stage"@en ;
|
|
164
164
|
rdfs:range xsd:string .
|
|
165
165
|
|
|
166
166
|
# =============================================================================
|
|
@@ -197,12 +197,12 @@ fit:CapabilityShape a sh:NodeShape ;
|
|
|
197
197
|
sh:description "Emoji for visual representation" ;
|
|
198
198
|
] ;
|
|
199
199
|
sh:property [
|
|
200
|
-
sh:path fit:
|
|
200
|
+
sh:path fit:ordinalRank ;
|
|
201
201
|
sh:datatype xsd:integer ;
|
|
202
202
|
sh:minInclusive 1 ;
|
|
203
203
|
sh:maxCount 1 ;
|
|
204
|
-
sh:name "
|
|
205
|
-
sh:description "
|
|
204
|
+
sh:name "ordinalRank" ;
|
|
205
|
+
sh:description "Numeric rank for ordering capabilities (1 = first)" ;
|
|
206
206
|
] ;
|
|
207
207
|
sh:property [
|
|
208
208
|
sh:path fit:description ;
|
|
@@ -425,16 +425,16 @@ fit:SkillStageShape a sh:NodeShape ;
|
|
|
425
425
|
sh:description "Primary focus for this stage" ;
|
|
426
426
|
] ;
|
|
427
427
|
sh:property [
|
|
428
|
-
sh:path fit:
|
|
428
|
+
sh:path fit:readChecklist ;
|
|
429
429
|
sh:datatype xsd:string ;
|
|
430
430
|
sh:minCount 1 ;
|
|
431
|
-
sh:name "
|
|
432
|
-
sh:description "
|
|
431
|
+
sh:name "readChecklist" ;
|
|
432
|
+
sh:description "Read-Then-Do Checklist: steps to follow in order during this stage" ;
|
|
433
433
|
] ;
|
|
434
434
|
sh:property [
|
|
435
|
-
sh:path fit:
|
|
435
|
+
sh:path fit:confirmChecklist ;
|
|
436
436
|
sh:datatype xsd:string ;
|
|
437
437
|
sh:minCount 1 ;
|
|
438
|
-
sh:name "
|
|
439
|
-
sh:description "
|
|
438
|
+
sh:name "confirmChecklist" ;
|
|
439
|
+
sh:description "Do-Then-Confirm Checklist: items to verify before moving to next stage" ;
|
|
440
440
|
] .
|
package/schema/rdf/defs.ttl
CHANGED
|
@@ -134,9 +134,9 @@ fit:emojiIcon a rdf:Property ;
|
|
|
134
134
|
rdfs:comment "Emoji for visual representation"@en ;
|
|
135
135
|
rdfs:range xsd:string .
|
|
136
136
|
|
|
137
|
-
fit:
|
|
138
|
-
rdfs:label "
|
|
139
|
-
rdfs:comment "
|
|
137
|
+
fit:ordinalRank a rdf:Property ;
|
|
138
|
+
rdfs:label "ordinalRank"@en ;
|
|
139
|
+
rdfs:comment "Numeric rank for ordering (1 = first)"@en ;
|
|
140
140
|
rdfs:range xsd:integer .
|
|
141
141
|
|
|
142
142
|
fit:ordinal a rdf:Property ;
|
package/schema/rdf/framework.ttl
CHANGED
|
@@ -22,6 +22,10 @@ fit:EntityDefinition a rdfs:Class ;
|
|
|
22
22
|
rdfs:label "Entity Definition"@en ;
|
|
23
23
|
rdfs:comment "Definition for an entity type used in pages and chapters"@en .
|
|
24
24
|
|
|
25
|
+
fit:Distribution a rdfs:Class ;
|
|
26
|
+
rdfs:label "Distribution"@en ;
|
|
27
|
+
rdfs:comment "Distribution configuration for publishing and installing the framework"@en .
|
|
28
|
+
|
|
25
29
|
# -----------------------------------------------------------------------------
|
|
26
30
|
# Properties
|
|
27
31
|
# -----------------------------------------------------------------------------
|
|
@@ -38,6 +42,18 @@ fit:entityDefinitions a rdf:Property ;
|
|
|
38
42
|
rdfs:domain fit:Framework ;
|
|
39
43
|
rdfs:range fit:EntityDefinition .
|
|
40
44
|
|
|
45
|
+
fit:distribution a rdf:Property ;
|
|
46
|
+
rdfs:label "distribution"@en ;
|
|
47
|
+
rdfs:comment "Distribution configuration for the framework"@en ;
|
|
48
|
+
rdfs:domain fit:Framework ;
|
|
49
|
+
rdfs:range fit:Distribution .
|
|
50
|
+
|
|
51
|
+
fit:siteUrl a rdf:Property ;
|
|
52
|
+
rdfs:label "siteUrl"@en ;
|
|
53
|
+
rdfs:comment "Base URL for the published static site"@en ;
|
|
54
|
+
rdfs:domain fit:Distribution ;
|
|
55
|
+
rdfs:range xsd:anyURI .
|
|
56
|
+
|
|
41
57
|
fit:entityType a rdf:Property ;
|
|
42
58
|
rdfs:label "entityType"@en ;
|
|
43
59
|
rdfs:comment "The type of entity this definition describes"@en ;
|
|
@@ -88,6 +104,28 @@ fit:FrameworkShape a sh:NodeShape ;
|
|
|
88
104
|
sh:node fit:EntityDefinitionShape ;
|
|
89
105
|
sh:name "entityDefinitions" ;
|
|
90
106
|
sh:description "Definitions for each entity type" ;
|
|
107
|
+
] ;
|
|
108
|
+
sh:property [
|
|
109
|
+
sh:path fit:distribution ;
|
|
110
|
+
sh:node fit:DistributionShape ;
|
|
111
|
+
sh:maxCount 1 ;
|
|
112
|
+
sh:name "distribution" ;
|
|
113
|
+
sh:description "Distribution configuration for the framework" ;
|
|
114
|
+
] .
|
|
115
|
+
|
|
116
|
+
# -----------------------------------------------------------------------------
|
|
117
|
+
# Distribution Shape
|
|
118
|
+
# -----------------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
fit:DistributionShape a sh:NodeShape ;
|
|
121
|
+
sh:targetClass fit:Distribution ;
|
|
122
|
+
sh:property [
|
|
123
|
+
sh:path fit:siteUrl ;
|
|
124
|
+
sh:datatype xsd:anyURI ;
|
|
125
|
+
sh:minCount 1 ;
|
|
126
|
+
sh:maxCount 1 ;
|
|
127
|
+
sh:name "siteUrl" ;
|
|
128
|
+
sh:description "Base URL for the published static site" ;
|
|
91
129
|
] .
|
|
92
130
|
|
|
93
131
|
# -----------------------------------------------------------------------------
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
# =============================================================================
|
|
8
8
|
# Skill Questions Schema
|
|
9
9
|
# =============================================================================
|
|
10
|
-
# Interview questions for assessing skills
|
|
10
|
+
# Interview questions for assessing skills, organized by role type
|
|
11
|
+
# (professional/management) and level.
|
|
11
12
|
# =============================================================================
|
|
12
13
|
|
|
13
14
|
# -----------------------------------------------------------------------------
|
|
@@ -18,6 +19,18 @@ fit:Question a rdfs:Class ;
|
|
|
18
19
|
rdfs:label "Question"@en ;
|
|
19
20
|
rdfs:comment "Interview question for assessing skills or behaviours"@en .
|
|
20
21
|
|
|
22
|
+
fit:RoleType a rdfs:Class ;
|
|
23
|
+
rdfs:label "RoleType"@en ;
|
|
24
|
+
rdfs:comment "Type of role: professional (IC) or management"@en .
|
|
25
|
+
|
|
26
|
+
fit:professional a fit:RoleType ;
|
|
27
|
+
rdfs:label "professional"@en ;
|
|
28
|
+
rdfs:comment "Professional/individual contributor roles"@en .
|
|
29
|
+
|
|
30
|
+
fit:management a fit:RoleType ;
|
|
31
|
+
rdfs:label "management"@en ;
|
|
32
|
+
rdfs:comment "Management roles"@en .
|
|
33
|
+
|
|
21
34
|
# -----------------------------------------------------------------------------
|
|
22
35
|
# Properties
|
|
23
36
|
# -----------------------------------------------------------------------------
|
|
@@ -58,6 +71,12 @@ fit:atLevel a rdf:Property ;
|
|
|
58
71
|
rdfs:domain fit:Question ;
|
|
59
72
|
rdfs:range fit:SkillLevel .
|
|
60
73
|
|
|
74
|
+
fit:forRoleType a rdf:Property ;
|
|
75
|
+
rdfs:label "forRoleType"@en ;
|
|
76
|
+
rdfs:comment "The role type this question is intended for (professional or management)"@en ;
|
|
77
|
+
rdfs:domain fit:Question ;
|
|
78
|
+
rdfs:range fit:RoleType .
|
|
79
|
+
|
|
61
80
|
# =============================================================================
|
|
62
81
|
# SHACL SHAPES
|
|
63
82
|
# =============================================================================
|
|
@@ -125,4 +144,12 @@ fit:SkillQuestionShape a sh:NodeShape ;
|
|
|
125
144
|
sh:maxCount 1 ;
|
|
126
145
|
sh:name "atLevel" ;
|
|
127
146
|
sh:description "The skill level this question is for" ;
|
|
147
|
+
] ;
|
|
148
|
+
sh:property [
|
|
149
|
+
sh:path fit:forRoleType ;
|
|
150
|
+
sh:in ( fit:professional fit:management ) ;
|
|
151
|
+
sh:minCount 1 ;
|
|
152
|
+
sh:maxCount 1 ;
|
|
153
|
+
sh:name "forRoleType" ;
|
|
154
|
+
sh:description "The role type this question is for" ;
|
|
128
155
|
] .
|
package/schema/rdf/stages.ttl
CHANGED
|
@@ -28,14 +28,14 @@ fit:handoffs a rdf:Property ;
|
|
|
28
28
|
rdfs:domain fit:Stage ;
|
|
29
29
|
rdfs:range fit:Handoff .
|
|
30
30
|
|
|
31
|
-
fit:
|
|
32
|
-
rdfs:label "
|
|
33
|
-
rdfs:comment "
|
|
31
|
+
fit:readChecklist a rdf:Property ;
|
|
32
|
+
rdfs:label "readChecklist"@en ;
|
|
33
|
+
rdfs:comment "Read-Then-Do Checklist: steps to follow in order during this stage"@en ;
|
|
34
34
|
rdfs:range xsd:string .
|
|
35
35
|
|
|
36
|
-
fit:
|
|
37
|
-
rdfs:label "
|
|
38
|
-
rdfs:comment "
|
|
36
|
+
fit:confirmChecklist a rdf:Property ;
|
|
37
|
+
rdfs:label "confirmChecklist"@en ;
|
|
38
|
+
rdfs:comment "Do-Then-Confirm Checklist: items to verify before handing off to next stage"@en ;
|
|
39
39
|
rdfs:range xsd:string .
|
|
40
40
|
|
|
41
41
|
fit:summary a rdf:Property ;
|
|
@@ -74,7 +74,7 @@ fit:StageShape a sh:NodeShape ;
|
|
|
74
74
|
sh:targetClass fit:Stage ;
|
|
75
75
|
sh:property [
|
|
76
76
|
sh:path fit:id ;
|
|
77
|
-
sh:in ( "specify" "plan" "code" "review" "deploy" ) ;
|
|
77
|
+
sh:in ( "specify" "plan" "onboard" "code" "review" "deploy" ) ;
|
|
78
78
|
sh:minCount 1 ;
|
|
79
79
|
sh:maxCount 1 ;
|
|
80
80
|
sh:name "id" ;
|
|
@@ -122,16 +122,16 @@ fit:StageShape a sh:NodeShape ;
|
|
|
122
122
|
sh:description "Restrictions on behaviour in this stage" ;
|
|
123
123
|
] ;
|
|
124
124
|
sh:property [
|
|
125
|
-
sh:path fit:
|
|
125
|
+
sh:path fit:readChecklist ;
|
|
126
126
|
sh:datatype xsd:string ;
|
|
127
|
-
sh:name "
|
|
128
|
-
sh:description "
|
|
127
|
+
sh:name "readChecklist" ;
|
|
128
|
+
sh:description "Read-Then-Do Checklist: steps to follow in order during this stage" ;
|
|
129
129
|
] ;
|
|
130
130
|
sh:property [
|
|
131
|
-
sh:path fit:
|
|
131
|
+
sh:path fit:confirmChecklist ;
|
|
132
132
|
sh:datatype xsd:string ;
|
|
133
|
-
sh:name "
|
|
134
|
-
sh:description "
|
|
133
|
+
sh:name "confirmChecklist" ;
|
|
134
|
+
sh:description "Do-Then-Confirm Checklist: items to verify before handing off to next stage" ;
|
|
135
135
|
] .
|
|
136
136
|
|
|
137
137
|
# -----------------------------------------------------------------------------
|
|
@@ -142,7 +142,7 @@ fit:HandoffShape a sh:NodeShape ;
|
|
|
142
142
|
sh:targetClass fit:Handoff ;
|
|
143
143
|
sh:property [
|
|
144
144
|
sh:path fit:targetStage ;
|
|
145
|
-
sh:in ( "specify" "plan" "code" "review" "deploy" ) ;
|
|
145
|
+
sh:in ( "specify" "plan" "onboard" "code" "review" "deploy" ) ;
|
|
146
146
|
sh:minCount 1 ;
|
|
147
147
|
sh:maxCount 1 ;
|
|
148
148
|
sh:name "targetStage" ;
|
package/{lib → src}/levels.js
RENAMED
|
@@ -54,30 +54,25 @@ export const BEHAVIOUR_MATURITY_ORDER = [
|
|
|
54
54
|
BehaviourMaturity.EXEMPLIFYING,
|
|
55
55
|
];
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
export const Stage = {
|
|
63
|
-
SPECIFY: "specify",
|
|
64
|
-
PLAN: "plan",
|
|
65
|
-
CODE: "code",
|
|
66
|
-
REVIEW: "review",
|
|
67
|
-
DEPLOY: "deploy",
|
|
68
|
-
};
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Data-driven Stage Functions
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Stage ordering is derived from loaded stage data, not hardcoded.
|
|
61
|
+
// Use getStageOrder(stages) to get stage IDs in lifecycle order.
|
|
69
62
|
|
|
70
63
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
64
|
+
* Get ordered stage IDs from loaded stage data
|
|
65
|
+
*
|
|
66
|
+
* Stages are defined in stages.yaml and their array order IS the
|
|
67
|
+
* canonical lifecycle order. This function extracts IDs preserving
|
|
68
|
+
* that order, similar to getCapabilityOrder for capabilities.
|
|
69
|
+
*
|
|
70
|
+
* @param {Object[]} stages - Loaded stages array from stages.yaml
|
|
71
|
+
* @returns {string[]} Stage IDs in lifecycle order
|
|
73
72
|
*/
|
|
74
|
-
export
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Stage.CODE,
|
|
78
|
-
Stage.REVIEW,
|
|
79
|
-
Stage.DEPLOY,
|
|
80
|
-
];
|
|
73
|
+
export function getStageOrder(stages) {
|
|
74
|
+
return stages.map((s) => s.id);
|
|
75
|
+
}
|
|
81
76
|
|
|
82
77
|
/**
|
|
83
78
|
* Skill capabilities (what capability area)
|
|
@@ -98,72 +93,44 @@ export const Capability = {
|
|
|
98
93
|
PRODUCT: "product",
|
|
99
94
|
};
|
|
100
95
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
* 2. Data & AI capabilities
|
|
106
|
-
* 3. Scale & reliability
|
|
107
|
-
* 4. People & process
|
|
108
|
-
* 5. Business, documentation & product
|
|
109
|
-
* @type {string[]}
|
|
110
|
-
*/
|
|
111
|
-
export const CAPABILITY_ORDER = [
|
|
112
|
-
Capability.DELIVERY,
|
|
113
|
-
Capability.DATA,
|
|
114
|
-
Capability.AI,
|
|
115
|
-
Capability.ML,
|
|
116
|
-
Capability.SCALE,
|
|
117
|
-
Capability.RELIABILITY,
|
|
118
|
-
Capability.PEOPLE,
|
|
119
|
-
Capability.PROCESS,
|
|
120
|
-
Capability.BUSINESS,
|
|
121
|
-
Capability.DOCUMENTATION,
|
|
122
|
-
Capability.PRODUCT,
|
|
123
|
-
];
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get the index of a capability in the ordered list
|
|
127
|
-
* @param {string} capability - The capability to look up
|
|
128
|
-
* @returns {number} The index (0-based), or -1 if not found
|
|
129
|
-
*/
|
|
130
|
-
export function getCapabilityIndex(capability) {
|
|
131
|
-
return CAPABILITY_ORDER.indexOf(capability);
|
|
132
|
-
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Data-driven Capability Functions
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// These functions work with loaded capability data for responsibility derivation
|
|
133
100
|
|
|
134
101
|
/**
|
|
135
|
-
*
|
|
136
|
-
* @param {
|
|
137
|
-
* @param {string}
|
|
138
|
-
* @returns {
|
|
102
|
+
* Get capability metadata from loaded capability data
|
|
103
|
+
* @param {Object[]} capabilities - Loaded capabilities array
|
|
104
|
+
* @param {string} capabilityId - The capability ID to look up
|
|
105
|
+
* @returns {Object|undefined} The capability object or undefined
|
|
139
106
|
*/
|
|
140
|
-
export function
|
|
141
|
-
return
|
|
107
|
+
export function getCapabilityById(capabilities, capabilityId) {
|
|
108
|
+
return capabilities.find((c) => c.id === capabilityId);
|
|
142
109
|
}
|
|
143
110
|
|
|
144
111
|
/**
|
|
145
|
-
*
|
|
146
|
-
* @param {
|
|
147
|
-
* @returns {
|
|
112
|
+
* Get ordered capability IDs from loaded capability data
|
|
113
|
+
* @param {Object[]} capabilities - Loaded capabilities array
|
|
114
|
+
* @returns {string[]} Capability IDs in display order
|
|
148
115
|
*/
|
|
149
|
-
export function
|
|
150
|
-
return [...
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return a.name.localeCompare(b.name);
|
|
154
|
-
});
|
|
116
|
+
export function getCapabilityOrder(capabilities) {
|
|
117
|
+
return [...capabilities]
|
|
118
|
+
.sort((a, b) => (a.ordinalRank || 0) - (b.ordinalRank || 0))
|
|
119
|
+
.map((c) => c.id);
|
|
155
120
|
}
|
|
156
121
|
|
|
157
122
|
/**
|
|
158
|
-
* Group skills by capability in
|
|
123
|
+
* Group skills by capability in display order
|
|
159
124
|
* @param {import('./levels.js').Skill[]} skills - Array of skills to group
|
|
160
|
-
* @
|
|
125
|
+
* @param {Object[]} capabilities - Loaded capabilities array for ordering
|
|
126
|
+
* @returns {Object<string, import('./levels.js').Skill[]>} Object with capabilities as keys (in display order)
|
|
161
127
|
*/
|
|
162
|
-
export function groupSkillsByCapability(skills) {
|
|
128
|
+
export function groupSkillsByCapability(skills, capabilities) {
|
|
129
|
+
const capabilityOrder = getCapabilityOrder(capabilities);
|
|
163
130
|
const result = {};
|
|
164
131
|
|
|
165
|
-
// Initialize all capabilities in order (ensures consistent key order)
|
|
166
|
-
for (const capability of
|
|
132
|
+
// Initialize all capabilities in display order (ensures consistent key order)
|
|
133
|
+
for (const capability of capabilityOrder) {
|
|
167
134
|
result[capability] = [];
|
|
168
135
|
}
|
|
169
136
|
|
|
@@ -186,32 +153,6 @@ export function groupSkillsByCapability(skills) {
|
|
|
186
153
|
return result;
|
|
187
154
|
}
|
|
188
155
|
|
|
189
|
-
// ============================================================================
|
|
190
|
-
// Data-driven Capability Functions
|
|
191
|
-
// ============================================================================
|
|
192
|
-
// These functions work with loaded capability data for responsibility derivation
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Get capability metadata from loaded capability data
|
|
196
|
-
* @param {Object[]} capabilities - Loaded capabilities array
|
|
197
|
-
* @param {string} capabilityId - The capability ID to look up
|
|
198
|
-
* @returns {Object|undefined} The capability object or undefined
|
|
199
|
-
*/
|
|
200
|
-
export function getCapabilityById(capabilities, capabilityId) {
|
|
201
|
-
return capabilities.find((c) => c.id === capabilityId);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Get ordered capability IDs from loaded capability data
|
|
206
|
-
* @param {Object[]} capabilities - Loaded capabilities array
|
|
207
|
-
* @returns {string[]} Capability IDs in display order
|
|
208
|
-
*/
|
|
209
|
-
export function getCapabilityOrder(capabilities) {
|
|
210
|
-
return [...capabilities]
|
|
211
|
-
.sort((a, b) => (a.displayOrder || 0) - (b.displayOrder || 0))
|
|
212
|
-
.map((c) => c.id);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
156
|
/**
|
|
216
157
|
* Get emoji for a capability from loaded capability data
|
|
217
158
|
* @param {Object[]} capabilities - Loaded capabilities array
|
|
@@ -400,10 +341,21 @@ export const SkillType = {
|
|
|
400
341
|
* @property {number} [expectedDurationMinutes] - Estimated time to ask and answer
|
|
401
342
|
*/
|
|
402
343
|
|
|
344
|
+
/**
|
|
345
|
+
* @typedef {Object<string, Question[]>} LevelQuestions - Questions organized by level
|
|
346
|
+
*/
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* @typedef {Object} RoleTypeQuestions
|
|
350
|
+
* @property {LevelQuestions} [professionalQuestions] - Questions for professional/IC roles
|
|
351
|
+
* @property {LevelQuestions} [managementQuestions] - Questions for management roles
|
|
352
|
+
*/
|
|
353
|
+
|
|
403
354
|
/**
|
|
404
355
|
* @typedef {Object} QuestionBank
|
|
405
|
-
* @property {Object<string,
|
|
406
|
-
* @property {Object<string,
|
|
356
|
+
* @property {Object<string, RoleTypeQuestions>} skillLevels - Questions by skill ID, then by role type (professional/management), then by level
|
|
357
|
+
* @property {Object<string, RoleTypeQuestions>} behaviourMaturities - Questions by behaviour ID, then by role type, then by maturity
|
|
358
|
+
* @property {Object<string, RoleTypeQuestions>} [capabilityLevels] - Questions by capability ID, then by role type, then by level
|
|
407
359
|
*/
|
|
408
360
|
|
|
409
361
|
/**
|
package/{lib → src}/loader.js
RENAMED
|
@@ -281,12 +281,16 @@ async function loadCapabilitiesFromDir(capabilitiesDir) {
|
|
|
281
281
|
* @returns {Promise<import('./levels.js').QuestionBank>}
|
|
282
282
|
*/
|
|
283
283
|
export async function loadQuestionFolder(questionsDir) {
|
|
284
|
-
const [skillLevels, behaviourMaturities] =
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
284
|
+
const [skillLevels, behaviourMaturities, capabilityLevels] =
|
|
285
|
+
await Promise.all([
|
|
286
|
+
loadQuestionsFromDir(join(questionsDir, "skills")),
|
|
287
|
+
loadQuestionsFromDir(join(questionsDir, "behaviours")),
|
|
288
|
+
loadQuestionsFromDir(join(questionsDir, "capabilities")).catch(
|
|
289
|
+
() => ({}),
|
|
290
|
+
),
|
|
291
|
+
]);
|
|
288
292
|
|
|
289
|
-
return { skillLevels, behaviourMaturities };
|
|
293
|
+
return { skillLevels, behaviourMaturities, capabilityLevels };
|
|
290
294
|
}
|
|
291
295
|
|
|
292
296
|
/**
|
package/{lib → src}/modifiers.js
RENAMED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* Full modifier logic is in @forwardimpact/model.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { Capability } from "./levels.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Valid skill capability names
|
|
11
|
+
* Valid skill capability names (derived from Capability enum)
|
|
12
12
|
* @type {Set<string>}
|
|
13
13
|
*/
|
|
14
|
-
const VALID_CAPABILITIES = new Set(
|
|
14
|
+
const VALID_CAPABILITIES = new Set(Object.values(Capability));
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Check if a key is a skill capability
|