@forwardimpact/pathway 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.
@@ -81,8 +81,8 @@ export function renderInterviewDetail(params) {
81
81
  return;
82
82
  }
83
83
 
84
- // State for current interview type (default to first: Screening)
85
- let currentType = "short";
84
+ // State for current interview type (default to first: Mission Fit)
85
+ let currentType = "mission";
86
86
 
87
87
  const page = div(
88
88
  { className: "interview-detail-page" },
@@ -194,23 +194,32 @@ function createInterviewSummary(interview) {
194
194
  { className: "interview-summary-header" },
195
195
  h2({}, `${typeInfo.icon} ${typeInfo.name}`),
196
196
  p({ className: "text-muted" }, typeInfo.description),
197
+ typeInfo.panel
198
+ ? p({ className: "text-muted" }, `Panel: ${typeInfo.panel}`)
199
+ : null,
197
200
  ),
198
201
  div(
199
202
  { className: "interview-summary-stats" },
200
203
  createBadge(`${interview.questions.length} questions`, "default"),
201
204
  createBadge(`~${interview.expectedDurationMinutes} minutes`, "secondary"),
202
- interview.coverage.skills.length > 0
205
+ interview.coverage.skills?.length > 0
203
206
  ? createBadge(
204
207
  `${interview.coverage.skills.length} skills covered`,
205
208
  "primary",
206
209
  )
207
210
  : null,
208
- interview.coverage.behaviours.length > 0
211
+ interview.coverage.behaviours?.length > 0
209
212
  ? createBadge(
210
213
  `${interview.coverage.behaviours.length} behaviours covered`,
211
214
  "primary",
212
215
  )
213
216
  : null,
217
+ interview.coverage.capabilities?.length > 0
218
+ ? createBadge(
219
+ `${interview.coverage.capabilities.length} capabilities covered`,
220
+ "primary",
221
+ )
222
+ : null,
214
223
  ),
215
224
  );
216
225
  }
@@ -226,6 +235,9 @@ function createQuestionsDisplay(interview, framework) {
226
235
  const behaviourQuestions = interview.questions.filter(
227
236
  (q) => q.targetType === "behaviour",
228
237
  );
238
+ const capabilityQuestions = interview.questions.filter(
239
+ (q) => q.targetType === "capability",
240
+ );
229
241
 
230
242
  const sections = [];
231
243
 
@@ -241,12 +253,21 @@ function createQuestionsDisplay(interview, framework) {
241
253
  if (behaviourQuestions.length > 0) {
242
254
  sections.push(
243
255
  createDetailSection({
244
- title: `${getConceptEmoji(framework, "behaviour")} Behaviour Questions (${behaviourQuestions.length})`,
256
+ title: `${getConceptEmoji(framework, "behaviour")} Stakeholder Simulation (${behaviourQuestions.length})`,
245
257
  content: createQuestionsList(behaviourQuestions),
246
258
  }),
247
259
  );
248
260
  }
249
261
 
262
+ if (capabilityQuestions.length > 0) {
263
+ sections.push(
264
+ createDetailSection({
265
+ title: `${getConceptEmoji(framework, "capability") || "🧩"} Decomposition Questions (${capabilityQuestions.length})`,
266
+ content: createQuestionsList(capabilityQuestions),
267
+ }),
268
+ );
269
+ }
270
+
250
271
  if (sections.length === 0) {
251
272
  return div(
252
273
  { className: "card" },
@@ -262,6 +283,7 @@ function createQuestionsDisplay(interview, framework) {
262
283
 
263
284
  /**
264
285
  * Create questions list
286
+ * @param {Array} questions - Questions to display
265
287
  */
266
288
  function createQuestionsList(questions) {
267
289
  return div(
@@ -272,10 +294,41 @@ function createQuestionsList(questions) {
272
294
 
273
295
  /**
274
296
  * Create question card
297
+ * @param {Object} questionEntry - Question entry
298
+ * @param {number} number - Question number
275
299
  */
276
300
  function createQuestionCard(questionEntry, number) {
277
301
  const { question, targetName, targetLevel } = questionEntry;
278
302
 
303
+ const contextSection = question.context
304
+ ? div(
305
+ { className: "question-context" },
306
+ h4({}, "Context:"),
307
+ p({}, question.context),
308
+ )
309
+ : null;
310
+
311
+ const decompositionPromptsList =
312
+ question.decompositionPrompts && question.decompositionPrompts.length > 0
313
+ ? div(
314
+ { className: "question-prompts" },
315
+ h4({}, "Guide candidate thinking:"),
316
+ ul(
317
+ {},
318
+ ...question.decompositionPrompts.map((prompt) => li({}, prompt)),
319
+ ),
320
+ )
321
+ : null;
322
+
323
+ const simulationPromptsList =
324
+ question.simulationPrompts && question.simulationPrompts.length > 0
325
+ ? div(
326
+ { className: "question-prompts" },
327
+ h4({}, "Steer the simulation:"),
328
+ ul({}, ...question.simulationPrompts.map((prompt) => li({}, prompt))),
329
+ )
330
+ : null;
331
+
279
332
  const followUpsList =
280
333
  question.followUps && question.followUps.length > 0
281
334
  ? div(
@@ -309,6 +362,9 @@ function createQuestionCard(questionEntry, number) {
309
362
  ),
310
363
  ),
311
364
  div({ className: "question-text" }, question.text),
365
+ contextSection,
366
+ decompositionPromptsList,
367
+ simulationPromptsList,
312
368
  followUpsList,
313
369
  lookingForList,
314
370
  );
@@ -45,7 +45,10 @@ export function renderLanding() {
45
45
  const stages = data.stages || [];
46
46
 
47
47
  // Calculate stats using centralized capability ordering
48
- const skillsByCapability = groupSkillsByCapability(data.skills);
48
+ const skillsByCapability = groupSkillsByCapability(
49
+ data.skills,
50
+ data.capabilities,
51
+ );
49
52
  const capabilityCount = Object.keys(skillsByCapability).length;
50
53
  const tools = aggregateTools(data.skills);
51
54
 
@@ -344,6 +344,7 @@ function createComparisonSelectorsSection({
344
344
  currentLabel: `Current (${currentGrade.id})`,
345
345
  targetLabel: `Target (${targetGrade.id})`,
346
346
  size: 400,
347
+ capabilities: data.capabilities,
347
348
  },
348
349
  ),
349
350
  createComparisonBehaviourRadar(
@@ -22,7 +22,7 @@ import {
22
22
  SKILL_LEVEL_ORDER,
23
23
  BEHAVIOUR_MATURITY_ORDER,
24
24
  groupSkillsByCapability,
25
- CAPABILITY_ORDER,
25
+ getCapabilityOrder,
26
26
  getCapabilityEmoji,
27
27
  getConceptEmoji,
28
28
  } from "@forwardimpact/schema/levels";
@@ -66,7 +66,10 @@ export function getAssessmentState() {
66
66
  */
67
67
  function getWizardSteps(data) {
68
68
  const { framework } = data;
69
- const skillsByCapability = groupSkillsByCapability(data.skills);
69
+ const skillsByCapability = groupSkillsByCapability(
70
+ data.skills,
71
+ data.capabilities,
72
+ );
70
73
  const steps = [
71
74
  {
72
75
  id: "intro",
@@ -77,7 +80,7 @@ function getWizardSteps(data) {
77
80
  ];
78
81
 
79
82
  // Add a step for each non-empty skill capability
80
- for (const capability of CAPABILITY_ORDER) {
83
+ for (const capability of getCapabilityOrder(data.capabilities)) {
81
84
  const skills = skillsByCapability[capability];
82
85
  if (skills && skills.length > 0) {
83
86
  steps.push({
@@ -277,7 +280,7 @@ function renderIntroStep(data) {
277
280
  div(
278
281
  {},
279
282
  h4({}, `${data.skills.length} Skills`),
280
- p({}, "Across " + CAPABILITY_ORDER.length + " capabilities"),
283
+ p({}, "Across " + data.capabilities.length + " capabilities"),
281
284
  ),
282
285
  ),
283
286
  div(
package/src/slides.html CHANGED
@@ -23,7 +23,9 @@
23
23
  "@forwardimpact/model/checklist": "/model/lib/checklist.js",
24
24
  "@forwardimpact/model/matching": "/model/lib/matching.js",
25
25
  "@forwardimpact/model/profile": "/model/lib/profile.js",
26
- "@forwardimpact/model/progression": "/model/lib/progression.js"
26
+ "@forwardimpact/model/progression": "/model/lib/progression.js",
27
+ "@forwardimpact/model/policies": "/model/lib/policies/index.js",
28
+ "@forwardimpact/model/toolkit": "/model/lib/toolkit.js"
27
29
  }
28
30
  }
29
31
  </script>
@@ -30,10 +30,15 @@ description: {{{description}}}{{#hasUseWhen}} Use When: {{{useWhen}}}{{/hasUseWh
30
30
  {{/hasStages}}
31
31
  {{#hasToolReferences}}
32
32
 
33
- # Required Tools
33
+ ## Required Tools
34
34
 
35
- Use these tools when applying this skill. Alternative tools require documented
36
- justification with acknowledged trade-offs.
35
+ **MANDATORY:** You MUST use these tools when applying this skill. These are
36
+ organizational standards that override general knowledge or personal preferences.
37
+
38
+ If a blocking constraint prevents use of a required tool, document in your
39
+ output: (1) which tool requirement you cannot meet, (2) the specific constraint
40
+ preventing compliance, and (3) the alternative approach with acknowledged
41
+ trade-offs.
37
42
 
38
43
  | Tool | Use When |
39
44
  | ---- | -------- |