@forwardimpact/pathway 0.25.12 → 0.25.20

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.
@@ -13,6 +13,80 @@ import Mustache from "mustache";
13
13
  import { BEHAVIOUR_MATURITY_ORDER } from "@forwardimpact/map/levels";
14
14
  import { trimValue, trimFields } from "../shared.js";
15
15
 
16
+ /**
17
+ * Build expectations paragraph from job expectations
18
+ * @param {Object|undefined} expectations
19
+ * @returns {string}
20
+ */
21
+ function buildExpectationsParagraph(expectations) {
22
+ if (!expectations) return "";
23
+ const exp = expectations;
24
+ const sentences = [];
25
+
26
+ if (exp.impactScope) {
27
+ sentences.push(`This role encompasses ${exp.impactScope.toLowerCase()}.`);
28
+ }
29
+ if (exp.autonomyExpectation) {
30
+ let autonomySentence = `You will ${exp.autonomyExpectation.toLowerCase()}`;
31
+ if (exp.influenceScope) {
32
+ autonomySentence +=
33
+ `, ${exp.influenceScope.toLowerCase()}` +
34
+ (exp.influenceScope.endsWith(".") ? "" : ".");
35
+ } else {
36
+ autonomySentence += exp.autonomyExpectation.endsWith(".") ? "" : ".";
37
+ }
38
+ sentences.push(autonomySentence);
39
+ } else if (exp.influenceScope) {
40
+ sentences.push(
41
+ exp.influenceScope + (exp.influenceScope.endsWith(".") ? "" : "."),
42
+ );
43
+ }
44
+ if (exp.complexityHandled) {
45
+ sentences.push(`You will handle ${exp.complexityHandled.toLowerCase()}.`);
46
+ }
47
+ return sentences.length > 0 ? sentences.join(" ") : "";
48
+ }
49
+
50
+ /**
51
+ * Build capability skill sections at the highest proficiency
52
+ * @param {Object} job
53
+ * @returns {Array}
54
+ */
55
+ function buildCapabilitySkills(job) {
56
+ const derivedResponsibilities = job.derivedResponsibilities || [];
57
+ if (derivedResponsibilities.length === 0) return [];
58
+
59
+ const highestProficiency = derivedResponsibilities[0].proficiency;
60
+ const topResponsibilities = derivedResponsibilities.filter(
61
+ (r) => r.proficiency === highestProficiency,
62
+ );
63
+
64
+ const skillsByCapability = {};
65
+ for (const skill of job.skillMatrix) {
66
+ if (skill.proficiency !== highestProficiency) continue;
67
+ if (!skillsByCapability[skill.capability]) {
68
+ skillsByCapability[skill.capability] = [];
69
+ }
70
+ skillsByCapability[skill.capability].push(skill);
71
+ }
72
+
73
+ return topResponsibilities
74
+ .filter((r) => skillsByCapability[r.capability]?.length > 0)
75
+ .map((r) => {
76
+ const skills = [...skillsByCapability[r.capability]].sort((a, b) =>
77
+ (a.skillName || "").localeCompare(b.skillName || ""),
78
+ );
79
+ return {
80
+ capabilityHeading: r.capabilityName.toUpperCase(),
81
+ responsibilityDescription: r.responsibility,
82
+ skills: skills.map((s) => ({
83
+ skillName: s.skillName,
84
+ proficiencyDescription: s.proficiencyDescription || "",
85
+ })),
86
+ };
87
+ });
88
+ }
89
+
16
90
  /**
17
91
  * Prepare job data for template rendering
18
92
  * @param {Object} params
@@ -29,42 +103,7 @@ function prepareJobDescriptionData({ job, discipline, level, track }) {
29
103
  roleSummary = roleSummary.replace(/\{roleTitle\}/g, roleTitle);
30
104
  roleSummary = roleSummary.replace(/\{specialization\}/g, specialization);
31
105
 
32
- // Build expectations paragraph
33
- let expectationsParagraph = "";
34
- if (job.expectations) {
35
- const exp = job.expectations;
36
- const expectationSentences = [];
37
-
38
- if (exp.impactScope) {
39
- expectationSentences.push(
40
- `This role encompasses ${exp.impactScope.toLowerCase()}.`,
41
- );
42
- }
43
- if (exp.autonomyExpectation) {
44
- let autonomySentence = `You will ${exp.autonomyExpectation.toLowerCase()}`;
45
- if (exp.influenceScope) {
46
- autonomySentence +=
47
- `, ${exp.influenceScope.toLowerCase()}` +
48
- (exp.influenceScope.endsWith(".") ? "" : ".");
49
- } else {
50
- autonomySentence += exp.autonomyExpectation.endsWith(".") ? "" : ".";
51
- }
52
- expectationSentences.push(autonomySentence);
53
- } else if (exp.influenceScope) {
54
- expectationSentences.push(
55
- exp.influenceScope + (exp.influenceScope.endsWith(".") ? "" : "."),
56
- );
57
- }
58
- if (exp.complexityHandled) {
59
- expectationSentences.push(
60
- `You will handle ${exp.complexityHandled.toLowerCase()}.`,
61
- );
62
- }
63
-
64
- if (expectationSentences.length > 0) {
65
- expectationsParagraph = expectationSentences.join(" ");
66
- }
67
- }
106
+ const expectationsParagraph = buildExpectationsParagraph(job.expectations);
68
107
 
69
108
  // Sort behaviours by maturity level (highest first)
70
109
  const sortedBehaviours = [...job.behaviourProfile].sort((a, b) => {
@@ -76,45 +115,7 @@ function prepareJobDescriptionData({ job, discipline, level, track }) {
76
115
  return indexB - indexA;
77
116
  });
78
117
 
79
- // Build capability skill sections at the highest skill proficiency
80
- let capabilitySkills = [];
81
- const derivedResponsibilities = job.derivedResponsibilities || [];
82
- if (derivedResponsibilities.length > 0) {
83
- // derivedResponsibilities is sorted: highest proficiency first, then by skill count
84
- const highestProficiency = derivedResponsibilities[0].proficiency;
85
-
86
- // Filter responsibilities to only the highest proficiency
87
- const topResponsibilities = derivedResponsibilities.filter(
88
- (r) => r.proficiency === highestProficiency,
89
- );
90
-
91
- // Group skill matrix entries by capability at the highest level
92
- const skillsByCapability = {};
93
- for (const skill of job.skillMatrix) {
94
- if (skill.proficiency !== highestProficiency) continue;
95
- if (!skillsByCapability[skill.capability]) {
96
- skillsByCapability[skill.capability] = [];
97
- }
98
- skillsByCapability[skill.capability].push(skill);
99
- }
100
-
101
- // Build capability sections in skill count order
102
- capabilitySkills = topResponsibilities
103
- .filter((r) => skillsByCapability[r.capability]?.length > 0)
104
- .map((r) => {
105
- const skills = [...skillsByCapability[r.capability]].sort((a, b) =>
106
- (a.skillName || "").localeCompare(b.skillName || ""),
107
- );
108
- return {
109
- capabilityHeading: r.capabilityName.toUpperCase(),
110
- responsibilityDescription: r.responsibility,
111
- skills: skills.map((s) => ({
112
- skillName: s.skillName,
113
- proficiencyDescription: s.proficiencyDescription || "",
114
- })),
115
- };
116
- });
117
- }
118
+ const capabilitySkills = buildCapabilitySkills(job);
118
119
 
119
120
  // Build qualification summary with placeholder replacement
120
121
  const qualificationSummary =
@@ -33,6 +33,107 @@ import { createToolkitTable } from "../toolkit/dom.js";
33
33
  * @param {string} [options.jobTemplate] - Mustache template for job description
34
34
  * @returns {HTMLElement}
35
35
  */
36
+ /**
37
+ * Build a job data object from a view for template rendering
38
+ * @param {Object} view
39
+ * @returns {Object}
40
+ */
41
+ function buildJobFromView(view) {
42
+ return {
43
+ title: view.title,
44
+ skillMatrix: view.skillMatrix,
45
+ behaviourProfile: view.behaviourProfile,
46
+ expectations: view.expectations,
47
+ derivedResponsibilities: view.derivedResponsibilities,
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Create the tables section for a job detail view
53
+ * @param {Object} view
54
+ * @returns {HTMLElement}
55
+ */
56
+ function createJobTablesSection(view) {
57
+ return div(
58
+ { className: "job-tables-section" },
59
+ createDetailSection({
60
+ title: "Behaviour Profile",
61
+ content: createBehaviourProfile(view.behaviourProfile),
62
+ }),
63
+ createDetailSection({
64
+ title: "Skill Matrix",
65
+ content: createSkillMatrix(view.skillMatrix, {
66
+ capabilityOrder: view.capabilityOrder,
67
+ }),
68
+ }),
69
+ view.toolkit && view.toolkit.length > 0
70
+ ? createDetailSection({
71
+ title: "Tool Kit",
72
+ content: createToolkitTable(view.toolkit),
73
+ })
74
+ : null,
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Create the page header with breadcrumb links
80
+ * @param {Object} view
81
+ * @param {boolean} showBackLink
82
+ * @returns {HTMLElement}
83
+ */
84
+ function createJobHeader(view, showBackLink) {
85
+ return div(
86
+ { className: "page-header" },
87
+ showBackLink
88
+ ? createBackLink("/job-builder", "← Back to Job Builder")
89
+ : null,
90
+ h1({ className: "page-title" }, view.title),
91
+ div(
92
+ { className: "page-description" },
93
+ "Generated from: ",
94
+ a({ href: `#/discipline/${view.disciplineId}` }, view.disciplineName),
95
+ " × ",
96
+ a({ href: `#/level/${view.levelId}` }, view.levelId),
97
+ " × ",
98
+ a({ href: `#/track/${view.trackId}` }, view.trackName),
99
+ ),
100
+ );
101
+ }
102
+
103
+ /**
104
+ * Create the expectations section if expectations exist
105
+ * @param {Object} view
106
+ * @returns {HTMLElement|null}
107
+ */
108
+ function createExpectationsSection(view) {
109
+ if (!view.expectations || Object.keys(view.expectations).length === 0) {
110
+ return null;
111
+ }
112
+ return createDetailSection({
113
+ title: "Expectations",
114
+ content: createExpectationsCard(view.expectations),
115
+ });
116
+ }
117
+
118
+ /**
119
+ * Create the radar charts section
120
+ * @param {Object} view
121
+ * @returns {HTMLElement}
122
+ */
123
+ function createRadarSection(view) {
124
+ return div(
125
+ { className: "section auto-grid-lg" },
126
+ createBehaviourRadar(view.behaviourProfile, {
127
+ title: "Behaviours Radar",
128
+ size: 420,
129
+ }),
130
+ createSkillRadar(view.skillMatrix, {
131
+ title: "Skills Radar",
132
+ size: 420,
133
+ }),
134
+ );
135
+ }
136
+
36
137
  export function jobToDOM(view, options = {}) {
37
138
  const {
38
139
  showBackLink = true,
@@ -46,107 +147,22 @@ export function jobToDOM(view, options = {}) {
46
147
  } = options;
47
148
 
48
149
  const hasEntities = discipline && level && jobTemplate;
150
+ const job = hasEntities ? buildJobFromView(view) : null;
151
+ const descParams = hasEntities
152
+ ? { job, discipline, level, track, template: jobTemplate }
153
+ : null;
49
154
 
50
155
  return div(
51
156
  { className: "job-detail-page" },
52
- // Header
53
- div(
54
- { className: "page-header" },
55
- showBackLink
56
- ? createBackLink("/job-builder", "← Back to Job Builder")
57
- : null,
58
- h1({ className: "page-title" }, view.title),
59
- div(
60
- { className: "page-description" },
61
- "Generated from: ",
62
- a({ href: `#/discipline/${view.disciplineId}` }, view.disciplineName),
63
- " × ",
64
- a({ href: `#/level/${view.levelId}` }, view.levelId),
65
- " × ",
66
- a({ href: `#/track/${view.trackId}` }, view.trackName),
67
- ),
68
- ),
69
-
70
- // Expectations card
71
- view.expectations && Object.keys(view.expectations).length > 0
72
- ? createDetailSection({
73
- title: "Expectations",
74
- content: createExpectationsCard(view.expectations),
75
- })
157
+ createJobHeader(view, showBackLink),
158
+ createExpectationsSection(view),
159
+ createRadarSection(view),
160
+ showJobDescriptionHtml && descParams
161
+ ? createJobDescriptionHtml(descParams)
76
162
  : null,
77
-
78
- // Radar charts
79
- div(
80
- { className: "section auto-grid-lg" },
81
- createBehaviourRadar(view.behaviourProfile, {
82
- title: "Behaviours Radar",
83
- size: 420,
84
- }),
85
- createSkillRadar(view.skillMatrix, {
86
- title: "Skills Radar",
87
- size: 420,
88
- }),
89
- ),
90
-
91
- // Job Description HTML (for print view)
92
- showJobDescriptionHtml && hasEntities
93
- ? createJobDescriptionHtml({
94
- job: {
95
- title: view.title,
96
- skillMatrix: view.skillMatrix,
97
- behaviourProfile: view.behaviourProfile,
98
- expectations: view.expectations,
99
- derivedResponsibilities: view.derivedResponsibilities,
100
- },
101
- discipline,
102
- level,
103
- track,
104
- template: jobTemplate,
105
- })
106
- : null,
107
-
108
- // Behaviour profile, Skill matrix, Toolkit, Driver coverage tables
109
- showTables
110
- ? div(
111
- { className: "job-tables-section" },
112
- // Behaviour profile table
113
- createDetailSection({
114
- title: "Behaviour Profile",
115
- content: createBehaviourProfile(view.behaviourProfile),
116
- }),
117
-
118
- createDetailSection({
119
- title: "Skill Matrix",
120
- content: createSkillMatrix(view.skillMatrix, {
121
- capabilityOrder: view.capabilityOrder,
122
- }),
123
- }),
124
-
125
- // Toolkit (after skill matrix)
126
- view.toolkit && view.toolkit.length > 0
127
- ? createDetailSection({
128
- title: "Tool Kit",
129
- content: createToolkitTable(view.toolkit),
130
- })
131
- : null,
132
- )
133
- : null,
134
-
135
- // Job Description (copyable markdown)
136
- showJobDescriptionMarkdown && hasEntities
137
- ? createJobDescriptionSection({
138
- job: {
139
- title: view.title,
140
- skillMatrix: view.skillMatrix,
141
- behaviourProfile: view.behaviourProfile,
142
- expectations: view.expectations,
143
- derivedResponsibilities: view.derivedResponsibilities,
144
- },
145
- discipline,
146
- level,
147
- track,
148
- template: jobTemplate,
149
- })
163
+ showTables ? createJobTablesSection(view) : null,
164
+ showJobDescriptionMarkdown && descParams
165
+ ? createJobDescriptionSection(descParams)
150
166
  : null,
151
167
  );
152
168
  }
@@ -35,14 +35,98 @@ import { createJsonLdScript, levelToJsonLd } from "../json-ld.js";
35
35
  * @param {boolean} [options.showBackLink=true] - Whether to show back navigation link
36
36
  * @returns {HTMLElement}
37
37
  */
38
+ /**
39
+ * Create a proficiency row for the base skill table
40
+ * @param {string} label
41
+ * @param {string} badgeClass
42
+ * @param {string|undefined} proficiency
43
+ * @returns {HTMLElement}
44
+ */
45
+ function createProficiencyRow(label, badgeClass, proficiency) {
46
+ return tr(
47
+ {},
48
+ td({}, span({ className: `badge ${badgeClass}` }, label)),
49
+ td(
50
+ {},
51
+ proficiency
52
+ ? createLevelDots(
53
+ SKILL_PROFICIENCY_ORDER.indexOf(proficiency),
54
+ SKILL_PROFICIENCY_ORDER.length,
55
+ )
56
+ : span({ className: "text-muted" }, "—"),
57
+ ),
58
+ );
59
+ }
60
+
61
+ /**
62
+ * Create the base skill proficiencies and behaviour maturity section
63
+ * @param {Object} view
64
+ * @returns {HTMLElement}
65
+ */
66
+ function createBaseProfileSection(view) {
67
+ const profs = view.baseSkillProficiencies || {};
68
+ return div(
69
+ { className: "detail-section" },
70
+ div(
71
+ { className: "content-columns" },
72
+ div(
73
+ { className: "column" },
74
+ heading2({ className: "section-title" }, "Base Skill Proficiencies"),
75
+ table(
76
+ { className: "level-table" },
77
+ thead({}, tr({}, th({}, "Type"), th({}, "Level"))),
78
+ tbody(
79
+ {},
80
+ createProficiencyRow("Primary", "badge-primary", profs.primary),
81
+ createProficiencyRow(
82
+ "Secondary",
83
+ "badge-secondary",
84
+ profs.secondary,
85
+ ),
86
+ createProficiencyRow("Broad", "badge-broad", profs.broad),
87
+ ),
88
+ ),
89
+ ),
90
+ div(
91
+ { className: "column" },
92
+ heading2({ className: "section-title" }, "Base Behaviour Maturity"),
93
+ view.baseBehaviourMaturity
94
+ ? table(
95
+ { className: "level-table" },
96
+ thead({}, tr({}, th({}, "Maturity"), th({}, "Level"))),
97
+ tbody(
98
+ {},
99
+ tr(
100
+ {},
101
+ td(
102
+ {},
103
+ view.baseBehaviourMaturity.charAt(0).toUpperCase() +
104
+ view.baseBehaviourMaturity.slice(1),
105
+ ),
106
+ td(
107
+ {},
108
+ createLevelDots(
109
+ BEHAVIOUR_MATURITY_ORDER.indexOf(
110
+ view.baseBehaviourMaturity,
111
+ ),
112
+ BEHAVIOUR_MATURITY_ORDER.length,
113
+ ),
114
+ ),
115
+ ),
116
+ ),
117
+ )
118
+ : p({ className: "text-muted" }, "—"),
119
+ ),
120
+ ),
121
+ );
122
+ }
123
+
38
124
  export function levelToDOM(level, { framework, showBackLink = true } = {}) {
39
125
  const view = prepareLevelDetail(level);
40
126
  const emoji = framework ? getConceptEmoji(framework, "level") : "📊";
41
127
  return div(
42
128
  { className: "detail-page level-detail" },
43
- // JSON-LD structured data
44
129
  createJsonLdScript(levelToJsonLd(level)),
45
- // Header
46
130
  div(
47
131
  { className: "page-header" },
48
132
  showBackLink ? createBackLink("/level", "← Back to Levels") : null,
@@ -68,7 +152,6 @@ export function levelToDOM(level, { framework, showBackLink = true } = {}) {
68
152
  : null,
69
153
  ),
70
154
 
71
- // Titles section
72
155
  view.professionalTitle || view.managementTitle
73
156
  ? div(
74
157
  { className: "detail-section" },
@@ -93,7 +176,6 @@ export function levelToDOM(level, { framework, showBackLink = true } = {}) {
93
176
  )
94
177
  : null,
95
178
 
96
- // Expectations
97
179
  view.expectations && Object.keys(view.expectations).length > 0
98
180
  ? div(
99
181
  { className: "detail-section" },
@@ -111,103 +193,6 @@ export function levelToDOM(level, { framework, showBackLink = true } = {}) {
111
193
  )
112
194
  : null,
113
195
 
114
- // Base Skill Proficiencies and Base Behaviour Maturity in two columns
115
- div(
116
- { className: "detail-section" },
117
- div(
118
- { className: "content-columns" },
119
- // Base Skill Proficiencies column
120
- div(
121
- { className: "column" },
122
- heading2({ className: "section-title" }, "Base Skill Proficiencies"),
123
- table(
124
- { className: "level-table" },
125
- thead({}, tr({}, th({}, "Type"), th({}, "Level"))),
126
- tbody(
127
- {},
128
- tr(
129
- {},
130
- td({}, span({ className: "badge badge-primary" }, "Primary")),
131
- td(
132
- {},
133
- view.baseSkillProficiencies?.primary
134
- ? createLevelDots(
135
- SKILL_PROFICIENCY_ORDER.indexOf(
136
- view.baseSkillProficiencies.primary,
137
- ),
138
- SKILL_PROFICIENCY_ORDER.length,
139
- )
140
- : span({ className: "text-muted" }, "—"),
141
- ),
142
- ),
143
- tr(
144
- {},
145
- td(
146
- {},
147
- span({ className: "badge badge-secondary" }, "Secondary"),
148
- ),
149
- td(
150
- {},
151
- view.baseSkillProficiencies?.secondary
152
- ? createLevelDots(
153
- SKILL_PROFICIENCY_ORDER.indexOf(
154
- view.baseSkillProficiencies.secondary,
155
- ),
156
- SKILL_PROFICIENCY_ORDER.length,
157
- )
158
- : span({ className: "text-muted" }, "—"),
159
- ),
160
- ),
161
- tr(
162
- {},
163
- td({}, span({ className: "badge badge-broad" }, "Broad")),
164
- td(
165
- {},
166
- view.baseSkillProficiencies?.broad
167
- ? createLevelDots(
168
- SKILL_PROFICIENCY_ORDER.indexOf(
169
- view.baseSkillProficiencies.broad,
170
- ),
171
- SKILL_PROFICIENCY_ORDER.length,
172
- )
173
- : span({ className: "text-muted" }, "—"),
174
- ),
175
- ),
176
- ),
177
- ),
178
- ),
179
- // Base Behaviour Maturity column
180
- div(
181
- { className: "column" },
182
- heading2({ className: "section-title" }, "Base Behaviour Maturity"),
183
- view.baseBehaviourMaturity
184
- ? table(
185
- { className: "level-table" },
186
- thead({}, tr({}, th({}, "Maturity"), th({}, "Level"))),
187
- tbody(
188
- {},
189
- tr(
190
- {},
191
- td(
192
- {},
193
- view.baseBehaviourMaturity.charAt(0).toUpperCase() +
194
- view.baseBehaviourMaturity.slice(1),
195
- ),
196
- td(
197
- {},
198
- createLevelDots(
199
- BEHAVIOUR_MATURITY_ORDER.indexOf(
200
- view.baseBehaviourMaturity,
201
- ),
202
- BEHAVIOUR_MATURITY_ORDER.length,
203
- ),
204
- ),
205
- ),
206
- ),
207
- )
208
- : p({ className: "text-muted" }, "—"),
209
- ),
210
- ),
211
- ),
196
+ createBaseProfileSection(view),
212
197
  );
213
198
  }
@@ -223,10 +223,43 @@ function formatTable(view) {
223
223
  }
224
224
 
225
225
  /**
226
- * Format single source deep dive
227
- * @param {Object} view - Questions view
228
- * @returns {string}
226
+ * Format a single question's detail lines
227
+ * @param {string[]} lines
228
+ * @param {Object} q - Flattened question
229
229
  */
230
+ function formatQuestionDetail(lines, q) {
231
+ lines.push(` • [${q.id}] ${q.text}`);
232
+ lines.push(` Duration: ${q.expectedDurationMinutes} min`);
233
+ if (q.context) {
234
+ lines.push(` Context: ${q.context}`);
235
+ }
236
+ if (q.simulationPrompts && q.simulationPrompts.length > 0) {
237
+ lines.push(" Steer the simulation:");
238
+ for (const prompt of q.simulationPrompts) {
239
+ lines.push(` - ${prompt}`);
240
+ }
241
+ }
242
+ if (q.decompositionPrompts && q.decompositionPrompts.length > 0) {
243
+ lines.push(" Guide candidate thinking:");
244
+ for (const prompt of q.decompositionPrompts) {
245
+ lines.push(` - ${prompt}`);
246
+ }
247
+ }
248
+ if (q.lookingFor.length > 0) {
249
+ lines.push(" Looking for:");
250
+ for (const item of q.lookingFor) {
251
+ lines.push(` - ${item}`);
252
+ }
253
+ }
254
+ if (q.followUps.length > 0) {
255
+ lines.push(" Follow-ups:");
256
+ for (const fu of q.followUps) {
257
+ lines.push(` → ${fu}`);
258
+ }
259
+ }
260
+ lines.push("");
261
+ }
262
+
230
263
  function formatSingleSource(view) {
231
264
  const lines = [];
232
265
  const { questions, stats } = view;
@@ -259,36 +292,7 @@ function formatSingleSource(view) {
259
292
 
260
293
  lines.push(level.toUpperCase());
261
294
  for (const q of byLevel[level]) {
262
- lines.push(` • [${q.id}] ${q.text}`);
263
- lines.push(` Duration: ${q.expectedDurationMinutes} min`);
264
- if (q.context) {
265
- lines.push(` Context: ${q.context}`);
266
- }
267
- if (q.simulationPrompts && q.simulationPrompts.length > 0) {
268
- lines.push(" Steer the simulation:");
269
- for (const prompt of q.simulationPrompts) {
270
- lines.push(` - ${prompt}`);
271
- }
272
- }
273
- if (q.decompositionPrompts && q.decompositionPrompts.length > 0) {
274
- lines.push(" Guide candidate thinking:");
275
- for (const prompt of q.decompositionPrompts) {
276
- lines.push(` - ${prompt}`);
277
- }
278
- }
279
- if (q.lookingFor.length > 0) {
280
- lines.push(" Looking for:");
281
- for (const item of q.lookingFor) {
282
- lines.push(` - ${item}`);
283
- }
284
- }
285
- if (q.followUps.length > 0) {
286
- lines.push(" Follow-ups:");
287
- for (const fu of q.followUps) {
288
- lines.push(` → ${fu}`);
289
- }
290
- }
291
- lines.push("");
295
+ formatQuestionDetail(lines, q);
292
296
  }
293
297
  }
294
298