@forwardimpact/pathway 0.4.0 → 0.6.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.
Files changed (245) hide show
  1. package/bin/{pathway.js → fit-pathway.js} +65 -153
  2. package/package.json +18 -41
  3. package/{app → src}/commands/agent.js +5 -2
  4. package/{app → src}/commands/behaviour.js +1 -1
  5. package/{app → src}/commands/command-factory.js +2 -2
  6. package/{app → src}/commands/discipline.js +1 -1
  7. package/{app → src}/commands/driver.js +2 -2
  8. package/{app → src}/commands/grade.js +2 -2
  9. package/{app → src}/commands/job.js +3 -3
  10. package/{app → src}/commands/serve.js +26 -4
  11. package/{app → src}/commands/site.js +24 -4
  12. package/{app → src}/commands/skill.js +3 -3
  13. package/{app → src}/commands/stage.js +1 -1
  14. package/{app → src}/commands/track.js +2 -2
  15. package/{app → src}/components/card.js +11 -1
  16. package/{app → src}/components/checklist.js +1 -1
  17. package/src/components/code-display.js +153 -0
  18. package/{app → src}/components/comparison-radar.js +1 -1
  19. package/{app → src}/components/detail.js +1 -1
  20. package/src/components/markdown-textarea.js +153 -0
  21. package/{app → src}/components/skill-matrix.js +1 -1
  22. package/{app → src}/css/bundles/app.css +14 -0
  23. package/{app → src}/css/components/badges.css +15 -8
  24. package/{app → src}/css/components/forms.css +23 -13
  25. package/{app → src}/css/components/surfaces.css +49 -3
  26. package/{app → src}/css/components/typography.css +1 -2
  27. package/{app → src}/css/pages/agent-builder.css +11 -102
  28. package/{app → src}/css/pages/detail.css +11 -1
  29. package/{app → src}/css/tokens.css +3 -0
  30. package/{app → src}/formatters/agent/dom.js +26 -71
  31. package/{app → src}/formatters/agent/profile.js +11 -6
  32. package/{app → src}/formatters/behaviour/dom.js +1 -1
  33. package/{app → src}/formatters/discipline/dom.js +1 -1
  34. package/{app → src}/formatters/driver/dom.js +1 -1
  35. package/{app → src}/formatters/grade/dom.js +7 -7
  36. package/{app → src}/formatters/grade/markdown.js +1 -1
  37. package/{app → src}/formatters/interview/dom.js +1 -1
  38. package/{app → src}/formatters/interview/markdown.js +1 -1
  39. package/{app → src}/formatters/interview/shared.js +3 -3
  40. package/{app → src}/formatters/job/description.js +1 -1
  41. package/{app → src}/formatters/job/dom.js +3 -3
  42. package/{app → src}/formatters/job/markdown.js +1 -1
  43. package/{app → src}/formatters/json-ld.js +1 -1
  44. package/{app → src}/formatters/progress/shared.js +3 -3
  45. package/{app → src}/formatters/skill/dom.js +69 -57
  46. package/{app → src}/formatters/skill/markdown.js +1 -1
  47. package/{app → src}/formatters/skill/shared.js +5 -3
  48. package/{app → src}/formatters/stage/microdata.js +2 -2
  49. package/{app → src}/formatters/stage/shared.js +3 -3
  50. package/{app → src}/formatters/tool/shared.js +6 -0
  51. package/{app → src}/formatters/track/dom.js +1 -1
  52. package/{app → src}/formatters/track/markdown.js +1 -1
  53. package/{app → src}/formatters/track/shared.js +4 -1
  54. package/{app → src}/handout-main.js +16 -12
  55. package/src/handout.html +43 -0
  56. package/{app → src}/index.html +23 -2
  57. package/{app → src}/lib/card-mappers.js +28 -1
  58. package/{app → src}/lib/job-cache.js +1 -1
  59. package/{app → src}/lib/render.js +1 -1
  60. package/{app → src}/pages/agent-builder.js +120 -76
  61. package/{app → src}/pages/assessment-results.js +1 -1
  62. package/{app → src}/pages/interview.js +1 -1
  63. package/{app → src}/pages/job-builder.js +1 -1
  64. package/{app → src}/pages/job.js +1 -1
  65. package/{app → src}/pages/landing.js +5 -2
  66. package/{app → src}/pages/self-assessment.js +1 -1
  67. package/{app → src}/pages/skill.js +1 -1
  68. package/{app → src}/pages/stage.js +5 -5
  69. package/{app → src}/pages/tool.js +1 -1
  70. package/{app → src}/slide-main.js +2 -2
  71. package/{app → src}/slides/chapter.js +8 -8
  72. package/{app → src}/slides/index.js +3 -3
  73. package/{app → src}/slides/job.js +1 -1
  74. package/{app → src}/slides/overview.js +9 -9
  75. package/{app → src}/slides/skill.js +1 -0
  76. package/{app → src}/slides.html +16 -1
  77. package/templates/agent.template.md +44 -13
  78. package/templates/job.template.md +14 -20
  79. package/templates/skill.template.md +20 -23
  80. package/LICENSE +0 -201
  81. package/README.md +0 -104
  82. package/app/components/markdown-textarea.js +0 -132
  83. package/app/handout.html +0 -28
  84. package/app/model/agent.js +0 -738
  85. package/app/model/checklist.js +0 -103
  86. package/app/model/derivation.js +0 -766
  87. package/app/model/index-generator.js +0 -65
  88. package/app/model/interview.js +0 -539
  89. package/app/model/job.js +0 -228
  90. package/app/model/levels.js +0 -601
  91. package/app/model/loader.js +0 -599
  92. package/app/model/matching.js +0 -888
  93. package/app/model/modifiers.js +0 -158
  94. package/app/model/profile.js +0 -259
  95. package/app/model/progression.js +0 -507
  96. package/app/model/schema-validation.js +0 -438
  97. package/app/model/validation.js +0 -2130
  98. package/examples/agents/.claude/skills/architecture-design/SKILL.md +0 -130
  99. package/examples/agents/.claude/skills/cloud-platforms/SKILL.md +0 -131
  100. package/examples/agents/.claude/skills/code-quality-review/SKILL.md +0 -108
  101. package/examples/agents/.claude/skills/devops-cicd/SKILL.md +0 -142
  102. package/examples/agents/.claude/skills/full-stack-development/SKILL.md +0 -134
  103. package/examples/agents/.claude/skills/sre-practices/SKILL.md +0 -163
  104. package/examples/agents/.claude/skills/technical-debt-management/SKILL.md +0 -164
  105. package/examples/agents/.github/agents/se-platform-code.agent.md +0 -132
  106. package/examples/agents/.github/agents/se-platform-plan.agent.md +0 -131
  107. package/examples/agents/.github/agents/se-platform-review.agent.md +0 -136
  108. package/examples/agents/.vscode/settings.json +0 -8
  109. package/examples/behaviours/_index.yaml +0 -8
  110. package/examples/behaviours/outcome_ownership.yaml +0 -43
  111. package/examples/behaviours/polymathic_knowledge.yaml +0 -41
  112. package/examples/behaviours/precise_communication.yaml +0 -39
  113. package/examples/behaviours/relentless_curiosity.yaml +0 -37
  114. package/examples/behaviours/systems_thinking.yaml +0 -40
  115. package/examples/capabilities/_index.yaml +0 -8
  116. package/examples/capabilities/business.yaml +0 -189
  117. package/examples/capabilities/delivery.yaml +0 -303
  118. package/examples/capabilities/people.yaml +0 -68
  119. package/examples/capabilities/reliability.yaml +0 -412
  120. package/examples/capabilities/scale.yaml +0 -378
  121. package/examples/copilot-setup-steps.yaml +0 -25
  122. package/examples/devcontainer.yaml +0 -21
  123. package/examples/disciplines/_index.yaml +0 -6
  124. package/examples/disciplines/data_engineering.yaml +0 -78
  125. package/examples/disciplines/engineering_management.yaml +0 -63
  126. package/examples/disciplines/software_engineering.yaml +0 -78
  127. package/examples/drivers.yaml +0 -202
  128. package/examples/framework.yaml +0 -69
  129. package/examples/grades.yaml +0 -115
  130. package/examples/questions/behaviours/outcome_ownership.yaml +0 -51
  131. package/examples/questions/behaviours/polymathic_knowledge.yaml +0 -47
  132. package/examples/questions/behaviours/precise_communication.yaml +0 -54
  133. package/examples/questions/behaviours/relentless_curiosity.yaml +0 -50
  134. package/examples/questions/behaviours/systems_thinking.yaml +0 -52
  135. package/examples/questions/skills/architecture_design.yaml +0 -53
  136. package/examples/questions/skills/cloud_platforms.yaml +0 -47
  137. package/examples/questions/skills/code_quality.yaml +0 -48
  138. package/examples/questions/skills/data_modeling.yaml +0 -45
  139. package/examples/questions/skills/devops.yaml +0 -46
  140. package/examples/questions/skills/full_stack_development.yaml +0 -47
  141. package/examples/questions/skills/sre_practices.yaml +0 -43
  142. package/examples/questions/skills/stakeholder_management.yaml +0 -48
  143. package/examples/questions/skills/team_collaboration.yaml +0 -42
  144. package/examples/questions/skills/technical_writing.yaml +0 -42
  145. package/examples/self-assessments.yaml +0 -64
  146. package/examples/stages.yaml +0 -131
  147. package/examples/tracks/_index.yaml +0 -5
  148. package/examples/tracks/platform.yaml +0 -49
  149. package/examples/tracks/sre.yaml +0 -48
  150. package/examples/vscode-settings.yaml +0 -17
  151. /package/{app → src}/commands/index.js +0 -0
  152. /package/{app → src}/commands/init.js +0 -0
  153. /package/{app → src}/commands/interview.js +0 -0
  154. /package/{app → src}/commands/progress.js +0 -0
  155. /package/{app → src}/commands/questions.js +0 -0
  156. /package/{app → src}/commands/tool.js +0 -0
  157. /package/{app → src}/components/action-buttons.js +0 -0
  158. /package/{app → src}/components/behaviour-profile.js +0 -0
  159. /package/{app → src}/components/builder.js +0 -0
  160. /package/{app → src}/components/error-page.js +0 -0
  161. /package/{app → src}/components/grid.js +0 -0
  162. /package/{app → src}/components/list.js +0 -0
  163. /package/{app → src}/components/modifier-table.js +0 -0
  164. /package/{app → src}/components/nav.js +0 -0
  165. /package/{app → src}/components/progression-table.js +0 -0
  166. /package/{app → src}/components/radar-chart.js +0 -0
  167. /package/{app → src}/css/base.css +0 -0
  168. /package/{app → src}/css/bundles/handout.css +0 -0
  169. /package/{app → src}/css/bundles/slides.css +0 -0
  170. /package/{app → src}/css/components/buttons.css +0 -0
  171. /package/{app → src}/css/components/layout.css +0 -0
  172. /package/{app → src}/css/components/nav.css +0 -0
  173. /package/{app → src}/css/components/progress.css +0 -0
  174. /package/{app → src}/css/components/states.css +0 -0
  175. /package/{app → src}/css/components/tables.css +0 -0
  176. /package/{app → src}/css/components/utilities.css +0 -0
  177. /package/{app → src}/css/pages/assessment-results.css +0 -0
  178. /package/{app → src}/css/pages/interview-builder.css +0 -0
  179. /package/{app → src}/css/pages/job-builder.css +0 -0
  180. /package/{app → src}/css/pages/landing.css +0 -0
  181. /package/{app → src}/css/pages/lifecycle.css +0 -0
  182. /package/{app → src}/css/pages/progress-builder.css +0 -0
  183. /package/{app → src}/css/pages/self-assessment.css +0 -0
  184. /package/{app → src}/css/reset.css +0 -0
  185. /package/{app → src}/css/views/handout.css +0 -0
  186. /package/{app → src}/css/views/print.css +0 -0
  187. /package/{app → src}/css/views/slide-animations.css +0 -0
  188. /package/{app → src}/css/views/slide-base.css +0 -0
  189. /package/{app → src}/css/views/slide-sections.css +0 -0
  190. /package/{app → src}/css/views/slide-tables.css +0 -0
  191. /package/{app → src}/formatters/agent/skill.js +0 -0
  192. /package/{app → src}/formatters/behaviour/markdown.js +0 -0
  193. /package/{app → src}/formatters/behaviour/microdata.js +0 -0
  194. /package/{app → src}/formatters/behaviour/shared.js +0 -0
  195. /package/{app → src}/formatters/discipline/markdown.js +0 -0
  196. /package/{app → src}/formatters/discipline/microdata.js +0 -0
  197. /package/{app → src}/formatters/discipline/shared.js +0 -0
  198. /package/{app → src}/formatters/driver/microdata.js +0 -0
  199. /package/{app → src}/formatters/driver/shared.js +0 -0
  200. /package/{app → src}/formatters/grade/microdata.js +0 -0
  201. /package/{app → src}/formatters/grade/shared.js +0 -0
  202. /package/{app → src}/formatters/index.js +0 -0
  203. /package/{app → src}/formatters/microdata-shared.js +0 -0
  204. /package/{app → src}/formatters/progress/dom.js +0 -0
  205. /package/{app → src}/formatters/progress/markdown.js +0 -0
  206. /package/{app → src}/formatters/questions/json.js +0 -0
  207. /package/{app → src}/formatters/questions/markdown.js +0 -0
  208. /package/{app → src}/formatters/questions/shared.js +0 -0
  209. /package/{app → src}/formatters/questions/yaml.js +0 -0
  210. /package/{app → src}/formatters/shared.js +0 -0
  211. /package/{app → src}/formatters/skill/microdata.js +0 -0
  212. /package/{app → src}/formatters/stage/dom.js +0 -0
  213. /package/{app → src}/formatters/stage/index.js +0 -0
  214. /package/{app → src}/formatters/track/microdata.js +0 -0
  215. /package/{app → src}/lib/cli-output.js +0 -0
  216. /package/{app → src}/lib/error-boundary.js +0 -0
  217. /package/{app → src}/lib/errors.js +0 -0
  218. /package/{app → src}/lib/form-controls.js +0 -0
  219. /package/{app → src}/lib/markdown.js +0 -0
  220. /package/{app → src}/lib/radar.js +0 -0
  221. /package/{app → src}/lib/reactive.js +0 -0
  222. /package/{app → src}/lib/router-core.js +0 -0
  223. /package/{app → src}/lib/router-pages.js +0 -0
  224. /package/{app → src}/lib/router-slides.js +0 -0
  225. /package/{app → src}/lib/state.js +0 -0
  226. /package/{app → src}/lib/template-loader.js +0 -0
  227. /package/{app → src}/lib/utils.js +0 -0
  228. /package/{app → src}/lib/yaml-loader.js +0 -0
  229. /package/{app → src}/main.js +0 -0
  230. /package/{app → src}/pages/behaviour.js +0 -0
  231. /package/{app → src}/pages/discipline.js +0 -0
  232. /package/{app → src}/pages/driver.js +0 -0
  233. /package/{app → src}/pages/grade.js +0 -0
  234. /package/{app → src}/pages/interview-builder.js +0 -0
  235. /package/{app → src}/pages/progress-builder.js +0 -0
  236. /package/{app → src}/pages/progress.js +0 -0
  237. /package/{app → src}/pages/track.js +0 -0
  238. /package/{app → src}/slides/behaviour.js +0 -0
  239. /package/{app → src}/slides/discipline.js +0 -0
  240. /package/{app → src}/slides/driver.js +0 -0
  241. /package/{app → src}/slides/grade.js +0 -0
  242. /package/{app → src}/slides/interview.js +0 -0
  243. /package/{app → src}/slides/progress.js +0 -0
  244. /package/{app → src}/slides/track.js +0 -0
  245. /package/{app → src}/types.js +0 -0
@@ -51,32 +51,12 @@
51
51
  }
52
52
 
53
53
  .agent-section .filename {
54
- font-family:
55
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
56
- font-size: var(--font-size-sm);
54
+ font-family: var(--font-family-mono);
55
+ font-size: var(--font-size-xs);
57
56
  color: var(--color-text-muted);
58
57
  margin-bottom: var(--space-sm);
59
58
  }
60
59
 
61
- .agent-section .code-block {
62
- background: var(--color-bg);
63
- border: 1px solid var(--color-border);
64
- border-radius: var(--radius-md);
65
- padding: var(--space-md);
66
- overflow-x: auto;
67
- font-family:
68
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
69
- font-size: var(--font-size-sm);
70
- line-height: 1.5;
71
- white-space: pre-wrap;
72
- word-break: break-word;
73
- }
74
-
75
- .agent-section .code-block code {
76
- font-family: inherit;
77
- font-size: inherit;
78
- }
79
-
80
60
  /* Agent cards grid */
81
61
  .agent-cards-grid {
82
62
  display: grid;
@@ -122,24 +102,16 @@
122
102
  font-size: 1.5rem;
123
103
  }
124
104
 
125
- .agent-card-filename {
126
- font-family:
127
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
128
- font-size: var(--font-size-sm);
129
- color: var(--color-text-muted);
130
- margin: 0;
131
- padding: 0 var(--space-md);
132
- padding-top: var(--space-sm);
133
- }
134
-
135
105
  .agent-card-preview {
136
106
  padding: var(--space-md);
137
107
  }
138
108
 
139
- .agent-card-preview .code-preview {
109
+ .agent-card-preview .code-display-container {
140
110
  margin: 0;
111
+ }
112
+
113
+ .agent-card-preview .code-display {
141
114
  max-height: 400px;
142
- overflow-y: auto;
143
115
  }
144
116
 
145
117
  /* Skill cards grid */
@@ -170,38 +142,16 @@
170
142
  font-size: var(--font-size-sm);
171
143
  }
172
144
 
173
- .skill-card-filename {
174
- font-family:
175
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
176
- font-size: var(--font-size-xs);
177
- color: var(--color-text-muted);
178
- margin: 0;
179
- padding: var(--space-xs) var(--space-md);
180
- }
181
-
182
145
  .skill-card-preview {
183
146
  padding: var(--space-sm) var(--space-md) var(--space-md);
184
147
  }
185
148
 
186
- .skill-card-preview .code-preview {
149
+ .skill-card-preview .code-display-container {
187
150
  margin: 0;
188
- max-height: 300px;
189
- overflow-y: auto;
190
151
  }
191
152
 
192
- /* Code preview */
193
- .code-preview {
194
- background: var(--color-bg);
195
- border: 1px solid var(--color-border);
196
- border-radius: var(--radius-md);
197
- padding: var(--space-sm);
198
- font-family:
199
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
200
- font-size: var(--font-size-xs);
201
- line-height: 1.4;
202
- white-space: pre-wrap;
203
- word-break: break-word;
204
- color: var(--color-text-muted);
153
+ .skill-card-preview .code-display {
154
+ max-height: 300px;
205
155
  }
206
156
 
207
157
  .skills-list {
@@ -210,30 +160,6 @@
210
160
  gap: var(--space-md);
211
161
  }
212
162
 
213
- .skill-header {
214
- display: flex;
215
- justify-content: space-between;
216
- align-items: center;
217
- padding: var(--space-sm) var(--space-md);
218
- background: var(--color-bg);
219
- border-bottom: 1px solid var(--color-border);
220
- }
221
-
222
- .skill-filename {
223
- font-family:
224
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
225
- font-size: var(--font-size-sm);
226
- color: var(--color-text-muted);
227
- }
228
-
229
- .skill-card .code-block {
230
- margin: 0;
231
- border: none;
232
- border-radius: 0;
233
- max-height: 300px;
234
- overflow-y: auto;
235
- }
236
-
237
163
  /* CLI hint */
238
164
  .cli-hint {
239
165
  background: var(--color-bg);
@@ -243,17 +169,6 @@
243
169
  margin-bottom: var(--space-sm);
244
170
  }
245
171
 
246
- .cli-command {
247
- display: flex;
248
- align-items: flex-start;
249
- gap: var(--space-md);
250
- }
251
-
252
- .cli-command .code-block {
253
- flex: 1;
254
- margin: 0;
255
- }
256
-
257
172
  /* Role agents list */
258
173
  .role-agents-list {
259
174
  display: flex;
@@ -295,9 +210,8 @@
295
210
  }
296
211
 
297
212
  .role-filename {
298
- font-family:
299
- ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
300
- font-size: var(--font-size-sm);
213
+ font-family: var(--font-family-mono);
214
+ font-size: var(--font-size-xs);
301
215
  color: var(--color-text-muted);
302
216
  }
303
217
 
@@ -315,11 +229,6 @@
315
229
  margin-bottom: var(--space-sm);
316
230
  }
317
231
 
318
- .role-agent-content .code-block {
319
- max-height: 400px;
320
- overflow-y: auto;
321
- }
322
-
323
232
  /* Stage agent preview */
324
233
  .stage-agent-preview .stage-header {
325
234
  display: flex;
@@ -69,11 +69,16 @@
69
69
  background: var(--color-surface);
70
70
  }
71
71
 
72
+ /*
73
+ * Table cells: 60px row height = 16px padding-top + 28px content + 16px padding-bottom
74
+ * Matches list-item height for visual consistency
75
+ */
72
76
  .tools-table th,
73
77
  .tools-table td {
74
78
  padding: var(--space-md) var(--space-lg);
75
79
  text-align: left;
76
80
  border-bottom: 1px solid var(--color-border);
81
+ height: 60px;
77
82
  }
78
83
 
79
84
  .tools-table th {
@@ -86,7 +91,12 @@
86
91
  }
87
92
 
88
93
  .tools-table th:first-child {
89
- width: 200px;
94
+ width: 260px;
95
+ white-space: nowrap;
96
+ }
97
+
98
+ .tools-table td:first-child {
99
+ white-space: nowrap;
90
100
  }
91
101
 
92
102
  .tools-table tbody tr:last-child td {
@@ -130,6 +130,9 @@
130
130
  --font-family:
131
131
  system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
132
132
  sans-serif;
133
+ --font-family-mono:
134
+ "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
135
+ Consolas, monospace;
133
136
  --font-size-xs: 0.75rem;
134
137
  --font-size-sm: 0.875rem;
135
138
  --font-size-base: 1rem;
@@ -16,6 +16,7 @@ import {
16
16
  details,
17
17
  summary,
18
18
  } from "../../lib/render.js";
19
+ import { createCodeDisplay } from "../../components/code-display.js";
19
20
  import { formatAgentProfile } from "./profile.js";
20
21
  import { formatAgentSkill } from "./skill.js";
21
22
  import { getStageEmoji } from "../stage/shared.js";
@@ -53,13 +54,12 @@ export function agentDeploymentToDOM({
53
54
  // Profile section
54
55
  section(
55
56
  { className: "agent-section" },
56
- div(
57
- { className: "section-header" },
58
- h2({}, "Agent Profile"),
59
- createCopyButton(profileContent),
60
- ),
61
- p({ className: "filename" }, profile.filename),
62
- createCodeBlock(profileContent),
57
+ h2({}, "Agent Profile"),
58
+ createCodeDisplay({
59
+ content: profileContent,
60
+ filename: profile.filename,
61
+ maxHeight: 600,
62
+ }),
63
63
  ),
64
64
 
65
65
  // Role Agents section
@@ -145,48 +145,6 @@ function createDownloadButton(
145
145
  return btn;
146
146
  }
147
147
 
148
- /**
149
- * Create a copy button for content
150
- * @param {string} content - Content to copy
151
- * @returns {HTMLElement}
152
- */
153
- function createCopyButton(content) {
154
- const btn = button({ className: "btn btn-sm copy-btn" }, "📋 Copy");
155
-
156
- btn.addEventListener("click", async () => {
157
- try {
158
- await navigator.clipboard.writeText(content);
159
- btn.textContent = "✓ Copied";
160
- setTimeout(() => {
161
- btn.textContent = "📋 Copy";
162
- }, 2000);
163
- } catch {
164
- btn.textContent = "Failed";
165
- setTimeout(() => {
166
- btn.textContent = "📋 Copy";
167
- }, 2000);
168
- }
169
- });
170
-
171
- return btn;
172
- }
173
-
174
- /**
175
- * Create a code block with content
176
- * @param {string} content - Code content
177
- * @returns {HTMLElement}
178
- */
179
- function createCodeBlock(content) {
180
- const pre = document.createElement("pre");
181
- pre.className = "code-block";
182
-
183
- const code = document.createElement("code");
184
- code.textContent = content;
185
-
186
- pre.appendChild(code);
187
- return pre;
188
- }
189
-
190
148
  /**
191
149
  * Create a skill card with content and copy button
192
150
  * @param {Object} skill - Skill with frontmatter and body
@@ -198,12 +156,11 @@ function createSkillCard(skill) {
198
156
 
199
157
  return div(
200
158
  { className: "skill-card" },
201
- div(
202
- { className: "skill-header" },
203
- span({ className: "skill-filename" }, filename),
204
- createCopyButton(content),
205
- ),
206
- createCodeBlock(content),
159
+ createCodeDisplay({
160
+ content,
161
+ filename,
162
+ maxHeight: 300,
163
+ }),
207
164
  );
208
165
  }
209
166
 
@@ -235,8 +192,10 @@ function createRoleAgentCard(agent) {
235
192
  { className: "text-muted role-description" },
236
193
  agent.frontmatter.description,
237
194
  ),
238
- div({ className: "role-agent-actions" }, createCopyButton(content)),
239
- createCodeBlock(content),
195
+ createCodeDisplay({
196
+ content,
197
+ maxHeight: 400,
198
+ }),
240
199
  ),
241
200
  );
242
201
  }
@@ -254,13 +213,10 @@ function createCliCommand(agentName) {
254
213
 
255
214
  const command = `npx pathway agent ${discipline} ${track} --output=.github --all-roles`;
256
215
 
257
- const container = div(
258
- { className: "cli-command" },
259
- createCodeBlock(command),
260
- createCopyButton(command),
261
- );
262
-
263
- return container;
216
+ return createCodeDisplay({
217
+ content: command,
218
+ language: "bash",
219
+ });
264
220
  }
265
221
 
266
222
  /**
@@ -445,13 +401,12 @@ export function stageAgentToDOM(stageAgent, profile, options = {}) {
445
401
  // Profile section
446
402
  section(
447
403
  { className: "agent-section" },
448
- div(
449
- { className: "section-header" },
450
- h3({}, "Agent Profile"),
451
- createCopyButton(profileContent),
452
- ),
453
- p({ className: "filename" }, profile.filename),
454
- createCodeBlock(profileContent),
404
+ h3({}, "Agent Profile"),
405
+ createCodeDisplay({
406
+ content: profileContent,
407
+ filename: profile.filename,
408
+ maxHeight: 600,
409
+ }),
455
410
  ),
456
411
 
457
412
  // Download button
@@ -26,7 +26,7 @@ import { trimValue, trimRequired, trimFields } from "../shared.js";
26
26
  * @param {string} params.bodyData.stageDescription - Stage description text
27
27
  * @param {string} params.bodyData.identity - Core identity text
28
28
  * @param {string} [params.bodyData.priority] - Priority/philosophy statement
29
- * @param {string[]} params.bodyData.capabilities - List of capability names
29
+ * @param {Array<{name: string, dirname: string, useWhen: string}>} params.bodyData.skillIndex - Skill index entries
30
30
  * @param {Array<{index: number, text: string}>} params.bodyData.beforeMakingChanges - Numbered steps
31
31
  * @param {string} [params.bodyData.delegation] - Delegation guidance
32
32
  * @param {string} params.bodyData.operationalContext - Operational context text
@@ -44,9 +44,13 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
44
44
 
45
45
  // Trim simple string arrays
46
46
  const constraints = (bodyData.constraints || []).map((c) => trimRequired(c));
47
- const capabilities = (bodyData.capabilities || []).map((c) =>
48
- trimRequired(c),
49
- );
47
+
48
+ // Trim skill index entries
49
+ const skillIndex = (bodyData.skillIndex || []).map((s) => ({
50
+ name: trimRequired(s.name),
51
+ dirname: trimRequired(s.dirname),
52
+ useWhen: trimRequired(s.useWhen),
53
+ }));
50
54
 
51
55
  return {
52
56
  // Frontmatter
@@ -60,7 +64,8 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
60
64
  stageDescription: trimValue(bodyData.stageDescription),
61
65
  identity: trimValue(bodyData.identity),
62
66
  priority: trimValue(bodyData.priority),
63
- capabilities,
67
+ skillIndex,
68
+ hasSkills: skillIndex.length > 0,
64
69
  beforeMakingChanges,
65
70
  delegation: trimValue(bodyData.delegation),
66
71
  operationalContext: trimValue(bodyData.operationalContext),
@@ -84,7 +89,7 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
84
89
  * @param {string} profile.bodyData.stageDescription - Stage description text
85
90
  * @param {string} profile.bodyData.identity - Core identity text
86
91
  * @param {string} [profile.bodyData.priority] - Priority/philosophy statement (optional)
87
- * @param {string[]} profile.bodyData.capabilities - List of capability names
92
+ * @param {Array<{name: string, dirname: string, useWhen: string}>} profile.bodyData.skillIndex - Skill index entries
88
93
  * @param {Array<{index: number, text: string}>} profile.bodyData.beforeMakingChanges - Numbered steps
89
94
  * @param {string} [profile.bodyData.delegation] - Delegation guidance (optional)
90
95
  * @param {string} profile.bodyData.operationalContext - Operational context text
@@ -21,7 +21,7 @@ import { createLevelCell } from "../../components/detail.js";
21
21
  import {
22
22
  BEHAVIOUR_MATURITY_ORDER,
23
23
  getConceptEmoji,
24
- } from "../../model/levels.js";
24
+ } from "@forwardimpact/schema/levels";
25
25
  import { prepareBehaviourDetail } from "./shared.js";
26
26
  import { createJsonLdScript, behaviourToJsonLd } from "../json-ld.js";
27
27
 
@@ -18,7 +18,7 @@ import {
18
18
  createJobBuilderButton,
19
19
  createInterviewPrepButton,
20
20
  } from "../../components/action-buttons.js";
21
- import { getConceptEmoji } from "../../model/levels.js";
21
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
22
22
  import { prepareDisciplineDetail } from "./shared.js";
23
23
  import { createJsonLdScript, disciplineToJsonLd } from "../json-ld.js";
24
24
  import { createBadge } from "../../components/card.js";
@@ -5,7 +5,7 @@
5
5
  import { div, heading1, heading2, p, a, span } from "../../lib/render.js";
6
6
  import { createBackLink } from "../../components/nav.js";
7
7
  import { prepareDriverDetail } from "./shared.js";
8
- import { getConceptEmoji } from "../../model/levels.js";
8
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
9
9
  import { createJsonLdScript, driverToJsonLd } from "../json-ld.js";
10
10
 
11
11
  /**
@@ -22,7 +22,7 @@ import {
22
22
  SKILL_LEVEL_ORDER,
23
23
  BEHAVIOUR_MATURITY_ORDER,
24
24
  getConceptEmoji,
25
- } from "../../model/levels.js";
25
+ } from "@forwardimpact/schema/levels";
26
26
  import { createJobBuilderButton } from "../../components/action-buttons.js";
27
27
  import { prepareGradeDetail } from "./shared.js";
28
28
  import { createJsonLdScript, gradeToJsonLd } from "../json-ld.js";
@@ -77,16 +77,16 @@ export function gradeToDOM(grade, { framework, showBackLink = true } = {}) {
77
77
  { className: "content-columns" },
78
78
  view.professionalTitle
79
79
  ? div(
80
- { className: "list-item" },
80
+ { className: "card" },
81
81
  p({ className: "label" }, "Professional Track"),
82
- p({}, view.professionalTitle),
82
+ p({ className: "card-description" }, view.professionalTitle),
83
83
  )
84
84
  : null,
85
85
  view.managementTitle
86
86
  ? div(
87
- { className: "list-item" },
87
+ { className: "card" },
88
88
  p({ className: "label" }, "Management Track"),
89
- p({}, view.managementTitle),
89
+ p({ className: "card-description" }, view.managementTitle),
90
90
  )
91
91
  : null,
92
92
  ),
@@ -102,9 +102,9 @@ export function gradeToDOM(grade, { framework, showBackLink = true } = {}) {
102
102
  { className: "content-columns" },
103
103
  ...Object.entries(view.expectations).map(([key, value]) =>
104
104
  div(
105
- { className: "list-item" },
105
+ { className: "card" },
106
106
  p({ className: "label" }, formatLevel(key)),
107
- p({}, value),
107
+ p({ className: "card-description" }, value),
108
108
  ),
109
109
  ),
110
110
  ),
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { tableToMarkdown, capitalize } from "../shared.js";
6
6
  import { prepareGradesList, prepareGradeDetail } from "./shared.js";
7
- import { getConceptEmoji } from "../../model/levels.js";
7
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
8
8
 
9
9
  /**
10
10
  * Format grade list as markdown
@@ -5,7 +5,7 @@
5
5
  import { div, heading1, heading2, p, span } from "../../lib/render.js";
6
6
  import { createBackLink } from "../../components/nav.js";
7
7
  import { createLevelDots } from "../../components/detail.js";
8
- import { getConceptEmoji } from "../../model/levels.js";
8
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
9
9
 
10
10
  /**
11
11
  * Format interview detail as DOM elements
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { formatLevel } from "../../lib/render.js";
6
- import { getConceptEmoji } from "../../model/levels.js";
6
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
7
7
 
8
8
  /**
9
9
  * Format interview detail as markdown
@@ -8,13 +8,13 @@ import {
8
8
  isValidJobCombination,
9
9
  generateJobTitle,
10
10
  getDisciplineSkillIds,
11
- } from "../../model/derivation.js";
11
+ } from "@forwardimpact/model/derivation";
12
12
  import {
13
13
  deriveInterviewQuestions,
14
14
  deriveShortInterview,
15
15
  deriveBehaviourQuestions,
16
- } from "../../model/interview.js";
17
- import { getOrCreateJob } from "../../lib/job-cache.js";
16
+ } from "@forwardimpact/model/interview";
17
+ import { getOrCreateJob } from "@forwardimpact/model/job-cache";
18
18
 
19
19
  /**
20
20
  * Interview type configurations
@@ -13,7 +13,7 @@ import Mustache from "mustache";
13
13
  import {
14
14
  SKILL_LEVEL_ORDER,
15
15
  BEHAVIOUR_MATURITY_ORDER,
16
- } from "../../model/levels.js";
16
+ } from "@forwardimpact/schema/levels";
17
17
  import { trimValue, trimFields } from "../shared.js";
18
18
 
19
19
  /**
@@ -14,7 +14,7 @@ import {
14
14
  } from "../../components/radar-chart.js";
15
15
  import { createSkillMatrix } from "../../components/skill-matrix.js";
16
16
  import { createBehaviourProfile } from "../../components/behaviour-profile.js";
17
- import { createMarkdownTextarea } from "../../components/markdown-textarea.js";
17
+ import { createCodeDisplay } from "../../components/code-display.js";
18
18
  import { markdownToHtml } from "../../lib/markdown.js";
19
19
  import { formatJobDescription } from "./description.js";
20
20
 
@@ -226,8 +226,8 @@ export function createJobDescriptionSection({
226
226
 
227
227
  return createDetailSection({
228
228
  title: "Job Description",
229
- content: createMarkdownTextarea({
230
- markdown,
229
+ content: createCodeDisplay({
230
+ content: markdown,
231
231
  description:
232
232
  "Copy this markdown-formatted job description for use in job postings, documentation, or sharing.",
233
233
  toHtml: markdownToHtml,
@@ -9,7 +9,7 @@ import {
9
9
  } from "../shared.js";
10
10
  import { formatLevel } from "../../lib/render.js";
11
11
  import { formatJobDescription } from "./description.js";
12
- import { SKILL_LEVEL_ORDER } from "../../model/levels.js";
12
+ import { SKILL_LEVEL_ORDER } from "@forwardimpact/schema/levels";
13
13
 
14
14
  /**
15
15
  * Format job detail as markdown
@@ -228,7 +228,7 @@ export function stageToJsonLd(stage) {
228
228
  identifier: stage.id,
229
229
  name: stage.name,
230
230
  description: stage.description,
231
- ...(stage.emoji && { emoji: stage.emoji }),
231
+ ...(stage.emojiIcon && { emojiIcon: stage.emojiIcon }),
232
232
  ...(stage.tools?.length > 0 && { tools: stage.tools }),
233
233
  ...(stage.constraints?.length > 0 && { constraints: stage.constraints }),
234
234
  ...(stage.handoffs && {
@@ -7,13 +7,13 @@
7
7
  import {
8
8
  isValidJobCombination,
9
9
  generateJobTitle,
10
- } from "../../model/derivation.js";
10
+ } from "@forwardimpact/model/derivation";
11
11
  import {
12
12
  analyzeProgression,
13
13
  analyzeCustomProgression,
14
14
  getNextGrade,
15
- } from "../../model/progression.js";
16
- import { getOrCreateJob } from "../../lib/job-cache.js";
15
+ } from "@forwardimpact/model/progression";
16
+ import { getOrCreateJob } from "@forwardimpact/model/job-cache";
17
17
 
18
18
  /**
19
19
  * Get the next grade for progression