@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
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
Capability,
|
|
9
|
-
Stage,
|
|
10
9
|
getSkillLevelIndex,
|
|
11
10
|
getBehaviourMaturityIndex,
|
|
12
11
|
} from "./levels.js";
|
|
@@ -150,14 +149,13 @@ function validateSkill(skill, index, requiredStageIds = []) {
|
|
|
150
149
|
),
|
|
151
150
|
);
|
|
152
151
|
} else {
|
|
153
|
-
// Validate each stage
|
|
154
|
-
const validStageIds = Object.values(Stage);
|
|
152
|
+
// Validate each stage against loaded stage data
|
|
155
153
|
for (const [stageId, stageData] of Object.entries(skill.agent.stages)) {
|
|
156
|
-
if (!
|
|
154
|
+
if (requiredStageIds.length > 0 && !requiredStageIds.includes(stageId)) {
|
|
157
155
|
errors.push(
|
|
158
156
|
createError(
|
|
159
157
|
"INVALID_VALUE",
|
|
160
|
-
`Invalid stage ID: ${stageId}. Must be one of: ${
|
|
158
|
+
`Invalid stage ID: ${stageId}. Must be one of: ${requiredStageIds.join(", ")}`,
|
|
161
159
|
`${agentPath}.stages.${stageId}`,
|
|
162
160
|
stageId,
|
|
163
161
|
),
|
|
@@ -184,41 +182,41 @@ function validateSkill(skill, index, requiredStageIds = []) {
|
|
|
184
182
|
),
|
|
185
183
|
);
|
|
186
184
|
}
|
|
187
|
-
//
|
|
188
|
-
if (!stageData.
|
|
185
|
+
// readChecklist is required and must be an array
|
|
186
|
+
if (!stageData.readChecklist) {
|
|
189
187
|
errors.push(
|
|
190
188
|
createError(
|
|
191
189
|
"MISSING_REQUIRED",
|
|
192
|
-
`Stage ${stageId} missing
|
|
193
|
-
`${stagePath}.
|
|
190
|
+
`Stage ${stageId} missing readChecklist`,
|
|
191
|
+
`${stagePath}.readChecklist`,
|
|
194
192
|
),
|
|
195
193
|
);
|
|
196
|
-
} else if (!Array.isArray(stageData.
|
|
194
|
+
} else if (!Array.isArray(stageData.readChecklist)) {
|
|
197
195
|
errors.push(
|
|
198
196
|
createError(
|
|
199
197
|
"INVALID_VALUE",
|
|
200
|
-
`Stage ${stageId}
|
|
201
|
-
`${stagePath}.
|
|
202
|
-
stageData.
|
|
198
|
+
`Stage ${stageId} readChecklist must be an array`,
|
|
199
|
+
`${stagePath}.readChecklist`,
|
|
200
|
+
stageData.readChecklist,
|
|
203
201
|
),
|
|
204
202
|
);
|
|
205
203
|
}
|
|
206
|
-
//
|
|
207
|
-
if (!stageData.
|
|
204
|
+
// confirmChecklist is required and must be an array (these become checklist items)
|
|
205
|
+
if (!stageData.confirmChecklist) {
|
|
208
206
|
errors.push(
|
|
209
207
|
createError(
|
|
210
208
|
"MISSING_REQUIRED",
|
|
211
|
-
`Stage ${stageId} missing
|
|
212
|
-
`${stagePath}.
|
|
209
|
+
`Stage ${stageId} missing confirmChecklist`,
|
|
210
|
+
`${stagePath}.confirmChecklist`,
|
|
213
211
|
),
|
|
214
212
|
);
|
|
215
|
-
} else if (!Array.isArray(stageData.
|
|
213
|
+
} else if (!Array.isArray(stageData.confirmChecklist)) {
|
|
216
214
|
errors.push(
|
|
217
215
|
createError(
|
|
218
216
|
"INVALID_VALUE",
|
|
219
|
-
`Stage ${stageId}
|
|
220
|
-
`${stagePath}.
|
|
221
|
-
stageData.
|
|
217
|
+
`Stage ${stageId} confirmChecklist must be an array`,
|
|
218
|
+
`${stagePath}.confirmChecklist`,
|
|
219
|
+
stageData.confirmChecklist,
|
|
222
220
|
),
|
|
223
221
|
);
|
|
224
222
|
}
|
|
@@ -284,7 +282,7 @@ function validateSkill(skill, index, requiredStageIds = []) {
|
|
|
284
282
|
errors.push(
|
|
285
283
|
createError(
|
|
286
284
|
"INVALID_FIELD",
|
|
287
|
-
"Skill agent 'verificationCriteria' field is not supported. Use stages.{stage}.
|
|
285
|
+
"Skill agent 'verificationCriteria' field is not supported. Use stages.{stage}.confirmChecklist instead.",
|
|
288
286
|
`${agentPath}.verificationCriteria`,
|
|
289
287
|
),
|
|
290
288
|
);
|
|
@@ -1249,15 +1247,6 @@ function validateStage(stage, index) {
|
|
|
1249
1247
|
|
|
1250
1248
|
if (!stage.id) {
|
|
1251
1249
|
errors.push(createError("MISSING_REQUIRED", "Stage missing id", path));
|
|
1252
|
-
} else if (!Object.values(Stage).includes(stage.id)) {
|
|
1253
|
-
errors.push(
|
|
1254
|
-
createError(
|
|
1255
|
-
"INVALID_VALUE",
|
|
1256
|
-
`Invalid stage id: ${stage.id}`,
|
|
1257
|
-
`${path}.id`,
|
|
1258
|
-
stage.id,
|
|
1259
|
-
),
|
|
1260
|
-
);
|
|
1261
1250
|
}
|
|
1262
1251
|
|
|
1263
1252
|
if (!stage.name) {
|
|
@@ -1774,6 +1763,7 @@ export function validateQuestionBank(questionBank, skills, behaviours) {
|
|
|
1774
1763
|
const warnings = [];
|
|
1775
1764
|
const skillIds = new Set(skills.map((s) => s.id));
|
|
1776
1765
|
const behaviourIds = new Set(behaviours.map((b) => b.id));
|
|
1766
|
+
const validRoleTypes = ["professionalQuestions", "managementQuestions"];
|
|
1777
1767
|
|
|
1778
1768
|
if (!questionBank) {
|
|
1779
1769
|
return createValidationResult(false, [
|
|
@@ -1784,7 +1774,7 @@ export function validateQuestionBank(questionBank, skills, behaviours) {
|
|
|
1784
1774
|
// Validate skill questions
|
|
1785
1775
|
if (questionBank.skillLevels) {
|
|
1786
1776
|
Object.entries(questionBank.skillLevels).forEach(
|
|
1787
|
-
([skillId,
|
|
1777
|
+
([skillId, roleTypeQuestions]) => {
|
|
1788
1778
|
if (!skillIds.has(skillId)) {
|
|
1789
1779
|
errors.push(
|
|
1790
1780
|
createError(
|
|
@@ -1795,27 +1785,46 @@ export function validateQuestionBank(questionBank, skills, behaviours) {
|
|
|
1795
1785
|
),
|
|
1796
1786
|
);
|
|
1797
1787
|
}
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1788
|
+
// Validate each role type (professional/management)
|
|
1789
|
+
Object.entries(roleTypeQuestions || {}).forEach(
|
|
1790
|
+
([roleType, levelQuestions]) => {
|
|
1791
|
+
if (!validRoleTypes.includes(roleType)) {
|
|
1792
|
+
errors.push(
|
|
1793
|
+
createError(
|
|
1794
|
+
"INVALID_VALUE",
|
|
1795
|
+
`Question bank has invalid role type: ${roleType}`,
|
|
1796
|
+
`questionBank.skillLevels.${skillId}.${roleType}`,
|
|
1797
|
+
roleType,
|
|
1798
|
+
),
|
|
1799
|
+
);
|
|
1800
|
+
return;
|
|
1801
|
+
}
|
|
1802
|
+
// Validate each level within the role type
|
|
1803
|
+
Object.entries(levelQuestions || {}).forEach(
|
|
1804
|
+
([level, questions]) => {
|
|
1805
|
+
if (getSkillLevelIndex(level) === -1) {
|
|
1806
|
+
errors.push(
|
|
1807
|
+
createError(
|
|
1808
|
+
"INVALID_VALUE",
|
|
1809
|
+
`Question bank has invalid skill level: ${level}`,
|
|
1810
|
+
`questionBank.skillLevels.${skillId}.${roleType}.${level}`,
|
|
1811
|
+
level,
|
|
1812
|
+
),
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
if (!Array.isArray(questions) || questions.length === 0) {
|
|
1816
|
+
warnings.push(
|
|
1817
|
+
createWarning(
|
|
1818
|
+
"EMPTY_QUESTIONS",
|
|
1819
|
+
`No questions for skill ${skillId} (${roleType}) at level ${level}`,
|
|
1820
|
+
`questionBank.skillLevels.${skillId}.${roleType}.${level}`,
|
|
1821
|
+
),
|
|
1822
|
+
);
|
|
1823
|
+
}
|
|
1824
|
+
},
|
|
1816
1825
|
);
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1826
|
+
},
|
|
1827
|
+
);
|
|
1819
1828
|
},
|
|
1820
1829
|
);
|
|
1821
1830
|
}
|
|
@@ -1823,7 +1832,7 @@ export function validateQuestionBank(questionBank, skills, behaviours) {
|
|
|
1823
1832
|
// Validate behaviour questions
|
|
1824
1833
|
if (questionBank.behaviourMaturities) {
|
|
1825
1834
|
Object.entries(questionBank.behaviourMaturities).forEach(
|
|
1826
|
-
([behaviourId,
|
|
1835
|
+
([behaviourId, roleTypeQuestions]) => {
|
|
1827
1836
|
if (!behaviourIds.has(behaviourId)) {
|
|
1828
1837
|
errors.push(
|
|
1829
1838
|
createError(
|
|
@@ -1834,27 +1843,44 @@ export function validateQuestionBank(questionBank, skills, behaviours) {
|
|
|
1834
1843
|
),
|
|
1835
1844
|
);
|
|
1836
1845
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1846
|
+
// Validate each role type (professional/management)
|
|
1847
|
+
Object.entries(roleTypeQuestions || {}).forEach(
|
|
1848
|
+
([roleType, maturityQuestions]) => {
|
|
1849
|
+
if (!validRoleTypes.includes(roleType)) {
|
|
1840
1850
|
errors.push(
|
|
1841
1851
|
createError(
|
|
1842
1852
|
"INVALID_VALUE",
|
|
1843
|
-
`Question bank has invalid
|
|
1844
|
-
`questionBank.behaviourMaturities.${behaviourId}.${
|
|
1845
|
-
|
|
1846
|
-
),
|
|
1847
|
-
);
|
|
1848
|
-
}
|
|
1849
|
-
if (!Array.isArray(questions) || questions.length === 0) {
|
|
1850
|
-
warnings.push(
|
|
1851
|
-
createWarning(
|
|
1852
|
-
"EMPTY_QUESTIONS",
|
|
1853
|
-
`No questions for behaviour ${behaviourId} at maturity ${maturity}`,
|
|
1854
|
-
`questionBank.behaviourMaturities.${behaviourId}.${maturity}`,
|
|
1853
|
+
`Question bank has invalid role type: ${roleType}`,
|
|
1854
|
+
`questionBank.behaviourMaturities.${behaviourId}.${roleType}`,
|
|
1855
|
+
roleType,
|
|
1855
1856
|
),
|
|
1856
1857
|
);
|
|
1858
|
+
return;
|
|
1857
1859
|
}
|
|
1860
|
+
// Validate each maturity level within the role type
|
|
1861
|
+
Object.entries(maturityQuestions || {}).forEach(
|
|
1862
|
+
([maturity, questions]) => {
|
|
1863
|
+
if (getBehaviourMaturityIndex(maturity) === -1) {
|
|
1864
|
+
errors.push(
|
|
1865
|
+
createError(
|
|
1866
|
+
"INVALID_VALUE",
|
|
1867
|
+
`Question bank has invalid behaviour maturity: ${maturity}`,
|
|
1868
|
+
`questionBank.behaviourMaturities.${behaviourId}.${roleType}.${maturity}`,
|
|
1869
|
+
maturity,
|
|
1870
|
+
),
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
if (!Array.isArray(questions) || questions.length === 0) {
|
|
1874
|
+
warnings.push(
|
|
1875
|
+
createWarning(
|
|
1876
|
+
"EMPTY_QUESTIONS",
|
|
1877
|
+
`No questions for behaviour ${behaviourId} (${roleType}) at maturity ${maturity}`,
|
|
1878
|
+
`questionBank.behaviourMaturities.${behaviourId}.${roleType}.${maturity}`,
|
|
1879
|
+
),
|
|
1880
|
+
);
|
|
1881
|
+
}
|
|
1882
|
+
},
|
|
1883
|
+
);
|
|
1858
1884
|
},
|
|
1859
1885
|
);
|
|
1860
1886
|
},
|
|
@@ -1960,7 +1986,7 @@ export function validateAgentData({ humanData, agentData }) {
|
|
|
1960
1986
|
|
|
1961
1987
|
// Validate skills with agent sections have complete stage coverage
|
|
1962
1988
|
const skillsWithAgent = (humanData.skills || []).filter((s) => s.agent);
|
|
1963
|
-
const requiredStages = ["plan", "code", "review"];
|
|
1989
|
+
const requiredStages = ["plan", "onboard", "code", "review"];
|
|
1964
1990
|
|
|
1965
1991
|
for (const skill of skillsWithAgent) {
|
|
1966
1992
|
const stages = skill.agent.stages || {};
|
|
@@ -1988,28 +2014,28 @@ export function validateAgentData({ humanData, agentData }) {
|
|
|
1988
2014
|
);
|
|
1989
2015
|
}
|
|
1990
2016
|
if (
|
|
1991
|
-
!stageData.
|
|
1992
|
-
!Array.isArray(stageData.
|
|
1993
|
-
stageData.
|
|
2017
|
+
!stageData.readChecklist ||
|
|
2018
|
+
!Array.isArray(stageData.readChecklist) ||
|
|
2019
|
+
stageData.readChecklist.length === 0
|
|
1994
2020
|
) {
|
|
1995
2021
|
errors.push(
|
|
1996
2022
|
createError(
|
|
1997
2023
|
"MISSING_REQUIRED",
|
|
1998
|
-
`Skill '${skill.id}' agent stage '${stageId}' missing or empty
|
|
1999
|
-
`skills.${skill.id}.agent.stages.${stageId}.
|
|
2024
|
+
`Skill '${skill.id}' agent stage '${stageId}' missing or empty readChecklist`,
|
|
2025
|
+
`skills.${skill.id}.agent.stages.${stageId}.readChecklist`,
|
|
2000
2026
|
),
|
|
2001
2027
|
);
|
|
2002
2028
|
}
|
|
2003
2029
|
if (
|
|
2004
|
-
!stageData.
|
|
2005
|
-
!Array.isArray(stageData.
|
|
2006
|
-
stageData.
|
|
2030
|
+
!stageData.confirmChecklist ||
|
|
2031
|
+
!Array.isArray(stageData.confirmChecklist) ||
|
|
2032
|
+
stageData.confirmChecklist.length === 0
|
|
2007
2033
|
) {
|
|
2008
2034
|
errors.push(
|
|
2009
2035
|
createError(
|
|
2010
2036
|
"MISSING_REQUIRED",
|
|
2011
|
-
`Skill '${skill.id}' agent stage '${stageId}' missing or empty
|
|
2012
|
-
`skills.${skill.id}.agent.stages.${stageId}.
|
|
2037
|
+
`Skill '${skill.id}' agent stage '${stageId}' missing or empty confirmChecklist`,
|
|
2038
|
+
`skills.${skill.id}.agent.stages.${stageId}.confirmChecklist`,
|
|
2013
2039
|
),
|
|
2014
2040
|
);
|
|
2015
2041
|
}
|
|
File without changes
|
/package/{lib → src}/index.js
RENAMED
|
File without changes
|
|
File without changes
|