@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.
- package/bin/fit-pathway.js +6 -5
- package/package.json +3 -3
- package/src/commands/agent.js +2 -2
- package/src/commands/interview.js +52 -14
- package/src/commands/questions.js +13 -10
- package/src/commands/skill.js +2 -2
- package/src/components/comparison-radar.js +7 -5
- package/src/css/components/badges.css +37 -27
- package/src/css/tokens.css +24 -20
- package/src/formatters/interview/markdown.js +62 -3
- package/src/formatters/interview/shared.js +89 -52
- package/src/formatters/questions/markdown.js +15 -0
- package/src/formatters/questions/shared.js +70 -58
- package/src/formatters/skill/shared.js +1 -1
- package/src/handout.html +3 -1
- package/src/index.html +3 -1
- package/src/lib/job-cache.js +7 -7
- package/src/lib/yaml-loader.js +39 -21
- package/src/pages/agent-builder.js +3 -3
- package/src/pages/interview.js +61 -5
- package/src/pages/landing.js +4 -1
- package/src/pages/progress.js +1 -0
- package/src/pages/self-assessment.js +7 -4
- package/src/slides.html +3 -1
- package/templates/skill.template.md +8 -3
package/bin/fit-pathway.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* stage [<id>] Show stages
|
|
19
19
|
* tool [<name>] Show tools
|
|
20
20
|
* job [<discipline> <grade>] [--track=TRACK] Generate job definition
|
|
21
|
-
* interview <discipline> <grade> [--track=TRACK] [--type=
|
|
21
|
+
* interview <discipline> <grade> [--track=TRACK] [--type=mission|decomposition|stakeholder] Generate interview
|
|
22
22
|
* progress <discipline> <grade> [--track=TRACK] [--compare=GRADE] Career progression
|
|
23
23
|
* questions [options] Browse interview questions
|
|
24
24
|
* agent [<discipline> <track>] [--output=PATH] Generate AI agent
|
|
@@ -167,13 +167,14 @@ INTERVIEW COMMAND
|
|
|
167
167
|
Generate interview question sets based on job requirements.
|
|
168
168
|
|
|
169
169
|
Usage:
|
|
170
|
-
npx fit-pathway interview <discipline> <grade>
|
|
171
|
-
npx fit-pathway interview <d> <g> --track=<track>
|
|
172
|
-
npx fit-pathway interview <d> <g> --type=<type>
|
|
170
|
+
npx fit-pathway interview <discipline> <grade> All types
|
|
171
|
+
npx fit-pathway interview <d> <g> --track=<track> With track
|
|
172
|
+
npx fit-pathway interview <d> <g> --track=<t> --type=<type> Single type
|
|
173
173
|
|
|
174
174
|
Options:
|
|
175
175
|
--track=TRACK Track specialization
|
|
176
|
-
--type=TYPE Interview type:
|
|
176
|
+
--type=TYPE Interview type: mission, decomposition, stakeholder
|
|
177
|
+
(omit for all types)
|
|
177
178
|
|
|
178
179
|
────────────────────────────────────────────────────────────────────────────────
|
|
179
180
|
PROGRESS COMMAND
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forwardimpact/pathway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Career progression web app and CLI for exploring roles and generating agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"./commands": "./src/commands/index.js"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@forwardimpact/schema": "^0.
|
|
44
|
-
"@forwardimpact/model": "^0.
|
|
43
|
+
"@forwardimpact/schema": "^0.6.0",
|
|
44
|
+
"@forwardimpact/model": "^0.7.0",
|
|
45
45
|
"mustache": "^4.2.0",
|
|
46
46
|
"simple-icons": "^16.7.0",
|
|
47
47
|
"yaml": "^2.3.4"
|
package/src/commands/agent.js
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
validateAgentSkill,
|
|
38
38
|
deriveReferenceGrade,
|
|
39
39
|
deriveAgentSkills,
|
|
40
|
-
|
|
40
|
+
generateSkillMarkdown,
|
|
41
41
|
deriveToolkit,
|
|
42
42
|
buildAgentIndex,
|
|
43
43
|
} from "@forwardimpact/model";
|
|
@@ -502,7 +502,7 @@ export async function runAgentCommand({ data, args, options, dataDir }) {
|
|
|
502
502
|
const skillFiles = derivedSkills
|
|
503
503
|
.map((derived) => skillsWithAgent.find((s) => s.id === derived.skillId))
|
|
504
504
|
.filter((skill) => skill?.agent)
|
|
505
|
-
.map((skill) =>
|
|
505
|
+
.map((skill) => generateSkillMarkdown(skill, data.stages));
|
|
506
506
|
|
|
507
507
|
// Validate all profiles
|
|
508
508
|
for (const profile of profiles) {
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Generates and displays interview questions in the terminal.
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
|
-
* npx pathway interview <discipline> <grade>
|
|
8
|
-
* npx pathway interview <discipline> <grade> --track=<track>
|
|
9
|
-
* npx pathway interview <discipline> <grade> --track=<track> --type=
|
|
7
|
+
* npx fit-pathway interview <discipline> <grade> # All interview types
|
|
8
|
+
* npx fit-pathway interview <discipline> <grade> --track=<track> # With track
|
|
9
|
+
* npx fit-pathway interview <discipline> <grade> --track=<track> --type=mission # Single type
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { createCompositeCommand } from "./command-factory.js";
|
|
@@ -16,8 +16,10 @@ import {
|
|
|
16
16
|
} from "../formatters/interview/shared.js";
|
|
17
17
|
import { interviewToMarkdown } from "../formatters/interview/markdown.js";
|
|
18
18
|
|
|
19
|
+
const VALID_TYPES = Object.keys(INTERVIEW_TYPES);
|
|
20
|
+
|
|
19
21
|
/**
|
|
20
|
-
* Format interview
|
|
22
|
+
* Format a single interview type as markdown
|
|
21
23
|
* @param {Object} view - Presenter view
|
|
22
24
|
* @param {Object} options - Options including framework
|
|
23
25
|
*/
|
|
@@ -25,15 +27,31 @@ function formatInterview(view, options) {
|
|
|
25
27
|
console.log(interviewToMarkdown(view, { framework: options.framework }));
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Format all interview types as markdown with separators
|
|
32
|
+
* @param {Array<Object>} views - Array of presenter views
|
|
33
|
+
* @param {Object} options - Options including framework
|
|
34
|
+
*/
|
|
35
|
+
function formatAllInterviews(views, options) {
|
|
36
|
+
for (let i = 0; i < views.length; i++) {
|
|
37
|
+
if (i > 0) {
|
|
38
|
+
console.log("\n" + "─".repeat(80) + "\n");
|
|
39
|
+
}
|
|
40
|
+
console.log(
|
|
41
|
+
interviewToMarkdown(views[i], { framework: options.framework }),
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
28
46
|
export const runInterviewCommand = createCompositeCommand({
|
|
29
47
|
commandName: "interview",
|
|
30
48
|
requiredArgs: ["discipline_id", "grade_id"],
|
|
31
49
|
findEntities: (data, args, options) => {
|
|
32
|
-
const interviewType = options.type
|
|
50
|
+
const interviewType = options.type === "full" ? null : options.type;
|
|
33
51
|
|
|
34
|
-
if (!INTERVIEW_TYPES[interviewType]) {
|
|
52
|
+
if (interviewType && !INTERVIEW_TYPES[interviewType]) {
|
|
35
53
|
console.error(`Unknown interview type: ${interviewType}`);
|
|
36
|
-
console.error(
|
|
54
|
+
console.error(`Available types: ${VALID_TYPES.join(", ")}`);
|
|
37
55
|
process.exit(1);
|
|
38
56
|
}
|
|
39
57
|
|
|
@@ -58,18 +76,38 @@ export const runInterviewCommand = createCompositeCommand({
|
|
|
58
76
|
}
|
|
59
77
|
return null;
|
|
60
78
|
},
|
|
61
|
-
presenter: (entities, data, _options) =>
|
|
62
|
-
|
|
79
|
+
presenter: (entities, data, _options) => {
|
|
80
|
+
const params = {
|
|
63
81
|
discipline: entities.discipline,
|
|
64
82
|
grade: entities.grade,
|
|
65
83
|
track: entities.track,
|
|
66
84
|
skills: data.skills,
|
|
67
85
|
behaviours: data.behaviours,
|
|
68
86
|
questions: data.questions,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Single type: return one view
|
|
90
|
+
if (entities.interviewType) {
|
|
91
|
+
return prepareInterviewDetail({
|
|
92
|
+
...params,
|
|
93
|
+
interviewType: entities.interviewType,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// All types: return array of views
|
|
98
|
+
return VALID_TYPES.map((type) =>
|
|
99
|
+
prepareInterviewDetail({ ...params, interviewType: type }),
|
|
100
|
+
).filter(Boolean);
|
|
101
|
+
},
|
|
102
|
+
formatter: (view, options, data) => {
|
|
103
|
+
const opts = { ...options, framework: data.framework };
|
|
104
|
+
|
|
105
|
+
if (Array.isArray(view)) {
|
|
106
|
+
formatAllInterviews(view, opts);
|
|
107
|
+
} else {
|
|
108
|
+
formatInterview(view, opts);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
73
111
|
usageExample:
|
|
74
|
-
"npx pathway interview software_engineering
|
|
112
|
+
"npx fit-pathway interview software_engineering J090 --track=platform --type=mission",
|
|
75
113
|
});
|
|
@@ -56,12 +56,15 @@ function showQuestionsSummary(data) {
|
|
|
56
56
|
"practitioner",
|
|
57
57
|
"expert",
|
|
58
58
|
];
|
|
59
|
+
const roleTypes = ["professionalQuestions", "managementQuestions"];
|
|
59
60
|
const skillRows = skillLevels.map((level) => {
|
|
60
61
|
let count = 0;
|
|
61
62
|
for (const skill of skills) {
|
|
62
|
-
const sq = questions.
|
|
63
|
-
if (sq
|
|
64
|
-
|
|
63
|
+
const sq = questions.skillLevels?.[skill.id];
|
|
64
|
+
if (sq) {
|
|
65
|
+
for (const roleType of roleTypes) {
|
|
66
|
+
count += (sq[roleType]?.[level] || []).length;
|
|
67
|
+
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
return [level, count];
|
|
@@ -81,9 +84,11 @@ function showQuestionsSummary(data) {
|
|
|
81
84
|
const behaviourRows = maturities.map((maturity) => {
|
|
82
85
|
let count = 0;
|
|
83
86
|
for (const behaviour of behaviours) {
|
|
84
|
-
const bq = questions.
|
|
85
|
-
if (bq
|
|
86
|
-
|
|
87
|
+
const bq = questions.behaviourMaturities?.[behaviour.id];
|
|
88
|
+
if (bq) {
|
|
89
|
+
for (const roleType of roleTypes) {
|
|
90
|
+
count += (bq[roleType]?.[maturity] || []).length;
|
|
91
|
+
}
|
|
87
92
|
}
|
|
88
93
|
}
|
|
89
94
|
return [maturity.replace(/_/g, " "), count];
|
|
@@ -138,10 +143,8 @@ export async function runQuestionsCommand({
|
|
|
138
143
|
behaviours: data.behaviours,
|
|
139
144
|
filter,
|
|
140
145
|
});
|
|
141
|
-
for (const
|
|
142
|
-
|
|
143
|
-
console.log(q.id);
|
|
144
|
-
}
|
|
146
|
+
for (const q of view.questions) {
|
|
147
|
+
console.log(q.id);
|
|
145
148
|
}
|
|
146
149
|
return;
|
|
147
150
|
}
|
package/src/commands/skill.js
CHANGED
|
@@ -16,7 +16,7 @@ import { skillToMarkdown } from "../formatters/skill/markdown.js";
|
|
|
16
16
|
import { prepareSkillsList } from "../formatters/skill/shared.js";
|
|
17
17
|
import { getConceptEmoji } from "@forwardimpact/schema/levels";
|
|
18
18
|
import { formatTable, formatError } from "../lib/cli-output.js";
|
|
19
|
-
import {
|
|
19
|
+
import { generateSkillMarkdown } from "@forwardimpact/model/agent";
|
|
20
20
|
import { formatAgentSkill } from "../formatters/agent/skill.js";
|
|
21
21
|
import { loadSkillTemplate } from "../lib/template-loader.js";
|
|
22
22
|
|
|
@@ -80,7 +80,7 @@ async function formatAgentDetail(skill, stages, dataDir) {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
const template = await loadSkillTemplate(dataDir);
|
|
83
|
-
const skillMd =
|
|
83
|
+
const skillMd = generateSkillMarkdown(skill, stages);
|
|
84
84
|
const output = formatAgentSkill(skillMd, template);
|
|
85
85
|
console.log(output);
|
|
86
86
|
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
getBehaviourMaturityIndex,
|
|
14
14
|
formatLevel,
|
|
15
15
|
} from "../lib/render.js";
|
|
16
|
-
import {
|
|
16
|
+
import { compareByCapability } from "@forwardimpact/model/policies";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Create a comparison skill radar chart
|
|
@@ -24,7 +24,7 @@ import { getCapabilityIndex } from "@forwardimpact/schema/levels";
|
|
|
24
24
|
*/
|
|
25
25
|
export function createComparisonSkillRadar(
|
|
26
26
|
currentMatrix,
|
|
27
|
-
targetMatrix,
|
|
27
|
+
targetMatrix = [],
|
|
28
28
|
options = {},
|
|
29
29
|
) {
|
|
30
30
|
const container = div(
|
|
@@ -80,9 +80,11 @@ export function createComparisonSkillRadar(
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// Sort by capability order, then by skill name within capability
|
|
83
|
+
const capabilityComparator = options.capabilities
|
|
84
|
+
? compareByCapability(options.capabilities)
|
|
85
|
+
: (a, b) => a.capability.localeCompare(b.capability);
|
|
83
86
|
skillEntries.sort((a, b) => {
|
|
84
|
-
const capDiff =
|
|
85
|
-
getCapabilityIndex(a.capability) - getCapabilityIndex(b.capability);
|
|
87
|
+
const capDiff = capabilityComparator(a, b);
|
|
86
88
|
if (capDiff !== 0) return capDiff;
|
|
87
89
|
return a.skillName.localeCompare(b.skillName);
|
|
88
90
|
});
|
|
@@ -141,7 +143,7 @@ export function createComparisonSkillRadar(
|
|
|
141
143
|
*/
|
|
142
144
|
export function createComparisonBehaviourRadar(
|
|
143
145
|
currentProfile,
|
|
144
|
-
targetProfile,
|
|
146
|
+
targetProfile = [],
|
|
145
147
|
options = {},
|
|
146
148
|
) {
|
|
147
149
|
const container = div(
|
|
@@ -93,50 +93,60 @@
|
|
|
93
93
|
font-weight: 500;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
/* Capability badges */
|
|
97
|
-
.badge-
|
|
98
|
-
background: var(--color-
|
|
99
|
-
color: var(--color-
|
|
96
|
+
/* Capability badges - each capability ID maps to its own distinct color */
|
|
97
|
+
.badge-ai {
|
|
98
|
+
background: var(--color-cap-ai-light);
|
|
99
|
+
color: var(--color-cap-ai);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
.badge-
|
|
103
|
-
background: var(--color-
|
|
104
|
-
color: var(--color-
|
|
102
|
+
.badge-business {
|
|
103
|
+
background: var(--color-cap-business-light);
|
|
104
|
+
color: var(--color-cap-business);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
.badge-
|
|
108
|
-
background: var(--color-
|
|
109
|
-
color: var(--color-
|
|
107
|
+
.badge-data {
|
|
108
|
+
background: var(--color-cap-data-light);
|
|
109
|
+
color: var(--color-cap-data);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
.badge-
|
|
113
|
-
background: var(--color-
|
|
114
|
-
color: var(--color-
|
|
112
|
+
.badge-delivery {
|
|
113
|
+
background: var(--color-cap-delivery-light);
|
|
114
|
+
color: var(--color-cap-delivery);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
.badge-
|
|
118
|
-
background: var(--color-
|
|
119
|
-
color: var(--color-
|
|
117
|
+
.badge-documentation {
|
|
118
|
+
background: var(--color-cap-documentation-light);
|
|
119
|
+
color: var(--color-cap-documentation);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.badge-ml {
|
|
123
|
+
background: var(--color-cap-ml-light);
|
|
124
|
+
color: var(--color-cap-ml);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.badge-people {
|
|
128
|
+
background: var(--color-cap-people-light);
|
|
129
|
+
color: var(--color-cap-people);
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
.badge-process {
|
|
123
|
-
background: var(--color-
|
|
124
|
-
color: var(--color-
|
|
133
|
+
background: var(--color-cap-process-light);
|
|
134
|
+
color: var(--color-cap-process);
|
|
125
135
|
}
|
|
126
136
|
|
|
127
|
-
.badge-
|
|
128
|
-
background: var(--color-
|
|
129
|
-
color: var(--color-
|
|
137
|
+
.badge-product {
|
|
138
|
+
background: var(--color-cap-product-light);
|
|
139
|
+
color: var(--color-cap-product);
|
|
130
140
|
}
|
|
131
141
|
|
|
132
|
-
.badge-
|
|
133
|
-
background: var(--color-
|
|
134
|
-
color: var(--color-
|
|
142
|
+
.badge-reliability {
|
|
143
|
+
background: var(--color-cap-reliability-light);
|
|
144
|
+
color: var(--color-cap-reliability);
|
|
135
145
|
}
|
|
136
146
|
|
|
137
|
-
.badge-
|
|
138
|
-
background: var(--color-
|
|
139
|
-
color: var(--color-
|
|
147
|
+
.badge-scale {
|
|
148
|
+
background: var(--color-cap-scale-light);
|
|
149
|
+
color: var(--color-cap-scale);
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
/* Tool badge */
|
package/src/css/tokens.css
CHANGED
|
@@ -43,30 +43,34 @@
|
|
|
43
43
|
--color-maturity-5: #c4b5fd;
|
|
44
44
|
|
|
45
45
|
/* --------------------------------------------------------------------------
|
|
46
|
-
Colors -
|
|
46
|
+
Colors - Capabilities (text) - matches data/capabilities/*.yaml IDs
|
|
47
47
|
-------------------------------------------------------------------------- */
|
|
48
|
-
--color-
|
|
49
|
-
--color-
|
|
50
|
-
--color-
|
|
51
|
-
--color-
|
|
52
|
-
--color-
|
|
53
|
-
--color-
|
|
54
|
-
--color-
|
|
55
|
-
--color-
|
|
56
|
-
--color-
|
|
48
|
+
--color-cap-ai: #7c3aed; /* violet */
|
|
49
|
+
--color-cap-business: #b45309; /* amber */
|
|
50
|
+
--color-cap-data: #0f766e; /* teal */
|
|
51
|
+
--color-cap-delivery: #dc2626; /* red */
|
|
52
|
+
--color-cap-documentation: #15803d; /* green */
|
|
53
|
+
--color-cap-ml: #9333ea; /* purple */
|
|
54
|
+
--color-cap-people: #be185d; /* pink */
|
|
55
|
+
--color-cap-process: #c2410c; /* orange */
|
|
56
|
+
--color-cap-product: #4f46e5; /* indigo */
|
|
57
|
+
--color-cap-reliability: #0891b2; /* cyan */
|
|
58
|
+
--color-cap-scale: #1d4ed8; /* blue */
|
|
57
59
|
|
|
58
60
|
/* --------------------------------------------------------------------------
|
|
59
|
-
Colors -
|
|
61
|
+
Colors - Capabilities (backgrounds)
|
|
60
62
|
-------------------------------------------------------------------------- */
|
|
61
|
-
--color-
|
|
62
|
-
--color-
|
|
63
|
-
--color-
|
|
64
|
-
--color-
|
|
65
|
-
--color-
|
|
66
|
-
--color-
|
|
67
|
-
--color-
|
|
68
|
-
--color-
|
|
69
|
-
--color-
|
|
63
|
+
--color-cap-ai-light: #ede9fe; /* violet */
|
|
64
|
+
--color-cap-business-light: #fef3c7; /* amber */
|
|
65
|
+
--color-cap-data-light: #ccfbf1; /* teal */
|
|
66
|
+
--color-cap-delivery-light: #fecaca; /* red */
|
|
67
|
+
--color-cap-documentation-light: #dcfce7; /* green */
|
|
68
|
+
--color-cap-ml-light: #f3e8ff; /* purple */
|
|
69
|
+
--color-cap-people-light: #fce7f3; /* pink */
|
|
70
|
+
--color-cap-process-light: #ffedd5; /* orange */
|
|
71
|
+
--color-cap-product-light: #e0e7ff; /* indigo */
|
|
72
|
+
--color-cap-reliability-light: #cffafe; /* cyan */
|
|
73
|
+
--color-cap-scale-light: #dbeafe; /* blue */
|
|
70
74
|
|
|
71
75
|
/* --------------------------------------------------------------------------
|
|
72
76
|
Colors - Neutrals
|
|
@@ -27,6 +27,9 @@ export function interviewToMarkdown(view, { framework } = {}) {
|
|
|
27
27
|
// Group sections by type
|
|
28
28
|
const skillSections = view.sections.filter((s) => s.type === "skill");
|
|
29
29
|
const behaviourSections = view.sections.filter((s) => s.type === "behaviour");
|
|
30
|
+
const capabilitySections = view.sections.filter(
|
|
31
|
+
(s) => s.type === "capability",
|
|
32
|
+
);
|
|
30
33
|
|
|
31
34
|
// Skill questions
|
|
32
35
|
if (skillSections.length > 0) {
|
|
@@ -36,27 +39,83 @@ export function interviewToMarkdown(view, { framework } = {}) {
|
|
|
36
39
|
for (const q of section.questions) {
|
|
37
40
|
lines.push(`**Q**: ${q.question}`);
|
|
38
41
|
if (q.followUps.length > 0) {
|
|
42
|
+
lines.push("", "**Follow-ups:**");
|
|
39
43
|
for (const followUp of q.followUps) {
|
|
40
44
|
lines.push(` → ${followUp}`);
|
|
41
45
|
}
|
|
42
46
|
}
|
|
47
|
+
if (q.lookingFor && q.lookingFor.length > 0) {
|
|
48
|
+
lines.push("", "**What to look for:**");
|
|
49
|
+
for (const item of q.lookingFor) {
|
|
50
|
+
lines.push(`- ${item}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
43
53
|
lines.push("");
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
|
|
48
|
-
//
|
|
58
|
+
// Capability decomposition questions
|
|
59
|
+
if (capabilitySections.length > 0) {
|
|
60
|
+
lines.push(`## 🧩 Decomposition Questions`, "");
|
|
61
|
+
for (const section of capabilitySections) {
|
|
62
|
+
lines.push(`### ${section.name} (${formatLevel(section.level)})`, "");
|
|
63
|
+
for (const q of section.questions) {
|
|
64
|
+
lines.push(`**Scenario**: ${q.question}`);
|
|
65
|
+
if (q.context) {
|
|
66
|
+
lines.push(`> ${q.context}`);
|
|
67
|
+
}
|
|
68
|
+
if (q.decompositionPrompts && q.decompositionPrompts.length > 0) {
|
|
69
|
+
lines.push("", "**Guide the candidate through:**");
|
|
70
|
+
for (const prompt of q.decompositionPrompts) {
|
|
71
|
+
lines.push(`- ${prompt}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (q.followUps.length > 0) {
|
|
75
|
+
lines.push("", "**Follow-ups:**");
|
|
76
|
+
for (const followUp of q.followUps) {
|
|
77
|
+
lines.push(` → ${followUp}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (q.lookingFor && q.lookingFor.length > 0) {
|
|
81
|
+
lines.push("", "**What to look for:**");
|
|
82
|
+
for (const item of q.lookingFor) {
|
|
83
|
+
lines.push(`- ${item}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
lines.push("");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Behaviour stakeholder simulation questions
|
|
49
92
|
if (behaviourSections.length > 0) {
|
|
50
|
-
lines.push(`## ${behaviourEmoji}
|
|
93
|
+
lines.push(`## ${behaviourEmoji} Stakeholder Simulation`, "");
|
|
51
94
|
for (const section of behaviourSections) {
|
|
52
95
|
lines.push(`### ${section.name} (${formatLevel(section.level)})`, "");
|
|
53
96
|
for (const q of section.questions) {
|
|
54
|
-
lines.push(`**
|
|
97
|
+
lines.push(`**Scenario**: ${q.question}`);
|
|
98
|
+
if (q.context) {
|
|
99
|
+
lines.push(`> ${q.context}`);
|
|
100
|
+
}
|
|
101
|
+
if (q.simulationPrompts && q.simulationPrompts.length > 0) {
|
|
102
|
+
lines.push("", "**Steer the simulation:**");
|
|
103
|
+
for (const prompt of q.simulationPrompts) {
|
|
104
|
+
lines.push(`- ${prompt}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
55
107
|
if (q.followUps.length > 0) {
|
|
108
|
+
lines.push("", "**Follow-ups:**");
|
|
56
109
|
for (const followUp of q.followUps) {
|
|
57
110
|
lines.push(` → ${followUp}`);
|
|
58
111
|
}
|
|
59
112
|
}
|
|
113
|
+
if (q.lookingFor && q.lookingFor.length > 0) {
|
|
114
|
+
lines.push("", "**What to look for:**");
|
|
115
|
+
for (const item of q.lookingFor) {
|
|
116
|
+
lines.push(`- ${item}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
60
119
|
lines.push("");
|
|
61
120
|
}
|
|
62
121
|
}
|