@forwardimpact/pathway 0.5.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.
Files changed (232) hide show
  1. package/README.md +47 -84
  2. package/bin/{pathway.js → fit-pathway.js} +65 -153
  3. package/package.json +18 -41
  4. package/{app → src}/commands/agent.js +5 -2
  5. package/{app → src}/commands/driver.js +1 -1
  6. package/{app → src}/commands/grade.js +1 -1
  7. package/{app → src}/commands/job.js +3 -3
  8. package/{app → src}/commands/serve.js +24 -2
  9. package/{app → src}/commands/site.js +2 -2
  10. package/{app → src}/commands/skill.js +2 -2
  11. package/{app → src}/commands/track.js +1 -1
  12. package/{app → src}/components/checklist.js +1 -1
  13. package/{app → src}/components/comparison-radar.js +1 -1
  14. package/{app → src}/components/detail.js +1 -1
  15. package/{app → src}/components/skill-matrix.js +1 -1
  16. package/{app → src}/formatters/behaviour/dom.js +1 -1
  17. package/{app → src}/formatters/behaviour/microdata.js +1 -1
  18. package/{app → src}/formatters/discipline/dom.js +1 -1
  19. package/{app → src}/formatters/discipline/microdata.js +1 -1
  20. package/{app → src}/formatters/driver/dom.js +1 -1
  21. package/{app → src}/formatters/driver/microdata.js +1 -1
  22. package/{app → src}/formatters/grade/dom.js +1 -1
  23. package/{app → src}/formatters/grade/markdown.js +1 -1
  24. package/{app → src}/formatters/grade/microdata.js +1 -1
  25. package/{app → src}/formatters/interview/dom.js +1 -1
  26. package/{app → src}/formatters/interview/markdown.js +1 -1
  27. package/{app → src}/formatters/interview/shared.js +3 -3
  28. package/{app → src}/formatters/job/description.js +1 -1
  29. package/{app → src}/formatters/job/markdown.js +1 -1
  30. package/{app → src}/formatters/json-ld.js +2 -2
  31. package/{app → src}/formatters/microdata-shared.js +2 -2
  32. package/{app → src}/formatters/progress/shared.js +3 -3
  33. package/{app → src}/formatters/skill/dom.js +1 -1
  34. package/{app → src}/formatters/skill/markdown.js +1 -1
  35. package/{app → src}/formatters/skill/microdata.js +1 -1
  36. package/{app → src}/formatters/skill/shared.js +2 -2
  37. package/{app → src}/formatters/stage/microdata.js +1 -1
  38. package/{app → src}/formatters/track/dom.js +1 -1
  39. package/{app → src}/formatters/track/markdown.js +1 -1
  40. package/{app → src}/formatters/track/microdata.js +1 -1
  41. package/{app → src}/formatters/track/shared.js +4 -1
  42. package/{app → src}/handout-main.js +4 -1
  43. package/src/handout.html +43 -0
  44. package/{app → src}/index.html +16 -1
  45. package/{app → src}/lib/card-mappers.js +1 -1
  46. package/{app → src}/lib/job-cache.js +1 -1
  47. package/{app → src}/lib/render.js +1 -1
  48. package/{app → src}/pages/agent-builder.js +1 -1
  49. package/{app → src}/pages/assessment-results.js +1 -1
  50. package/{app → src}/pages/interview.js +1 -1
  51. package/{app → src}/pages/job-builder.js +1 -1
  52. package/{app → src}/pages/job.js +1 -1
  53. package/{app → src}/pages/landing.js +4 -1
  54. package/{app → src}/pages/self-assessment.js +1 -1
  55. package/{app → src}/pages/skill.js +1 -1
  56. package/{app → src}/pages/stage.js +1 -1
  57. package/{app → src}/pages/tool.js +1 -1
  58. package/{app → src}/slide-main.js +1 -1
  59. package/{app → src}/slides/index.js +2 -2
  60. package/{app → src}/slides/job.js +1 -1
  61. package/{app → src}/slides/overview.js +1 -1
  62. package/{app → src}/slides.html +16 -1
  63. package/templates/agent.template.md +27 -26
  64. package/templates/job.template.md +11 -17
  65. package/templates/skill.template.md +15 -21
  66. package/app/handout.html +0 -28
  67. package/app/model/agent.js +0 -754
  68. package/app/model/checklist.js +0 -103
  69. package/app/model/derivation.js +0 -766
  70. package/app/model/index-generator.js +0 -65
  71. package/app/model/interview.js +0 -539
  72. package/app/model/job.js +0 -228
  73. package/app/model/levels.js +0 -601
  74. package/app/model/loader.js +0 -599
  75. package/app/model/matching.js +0 -888
  76. package/app/model/modifiers.js +0 -158
  77. package/app/model/profile.js +0 -259
  78. package/app/model/progression.js +0 -507
  79. package/app/model/schema-validation.js +0 -438
  80. package/app/model/validation.js +0 -2130
  81. package/examples/behaviours/_index.yaml +0 -8
  82. package/examples/behaviours/outcome_ownership.yaml +0 -43
  83. package/examples/behaviours/polymathic_knowledge.yaml +0 -41
  84. package/examples/behaviours/precise_communication.yaml +0 -39
  85. package/examples/behaviours/relentless_curiosity.yaml +0 -37
  86. package/examples/behaviours/systems_thinking.yaml +0 -40
  87. package/examples/capabilities/_index.yaml +0 -8
  88. package/examples/capabilities/business.yaml +0 -189
  89. package/examples/capabilities/delivery.yaml +0 -305
  90. package/examples/capabilities/people.yaml +0 -68
  91. package/examples/capabilities/reliability.yaml +0 -414
  92. package/examples/capabilities/scale.yaml +0 -378
  93. package/examples/copilot-setup-steps.yaml +0 -25
  94. package/examples/devcontainer.yaml +0 -21
  95. package/examples/disciplines/_index.yaml +0 -6
  96. package/examples/disciplines/data_engineering.yaml +0 -78
  97. package/examples/disciplines/engineering_management.yaml +0 -63
  98. package/examples/disciplines/software_engineering.yaml +0 -78
  99. package/examples/drivers.yaml +0 -202
  100. package/examples/framework.yaml +0 -69
  101. package/examples/grades.yaml +0 -115
  102. package/examples/questions/behaviours/outcome_ownership.yaml +0 -51
  103. package/examples/questions/behaviours/polymathic_knowledge.yaml +0 -47
  104. package/examples/questions/behaviours/precise_communication.yaml +0 -54
  105. package/examples/questions/behaviours/relentless_curiosity.yaml +0 -50
  106. package/examples/questions/behaviours/systems_thinking.yaml +0 -52
  107. package/examples/questions/skills/architecture_design.yaml +0 -53
  108. package/examples/questions/skills/cloud_platforms.yaml +0 -47
  109. package/examples/questions/skills/code_quality.yaml +0 -48
  110. package/examples/questions/skills/data_modeling.yaml +0 -45
  111. package/examples/questions/skills/devops.yaml +0 -46
  112. package/examples/questions/skills/full_stack_development.yaml +0 -47
  113. package/examples/questions/skills/sre_practices.yaml +0 -43
  114. package/examples/questions/skills/stakeholder_management.yaml +0 -48
  115. package/examples/questions/skills/team_collaboration.yaml +0 -42
  116. package/examples/questions/skills/technical_writing.yaml +0 -42
  117. package/examples/self-assessments.yaml +0 -64
  118. package/examples/stages.yaml +0 -139
  119. package/examples/tracks/_index.yaml +0 -5
  120. package/examples/tracks/platform.yaml +0 -49
  121. package/examples/tracks/sre.yaml +0 -48
  122. package/examples/vscode-settings.yaml +0 -17
  123. /package/{app → src}/commands/behaviour.js +0 -0
  124. /package/{app → src}/commands/command-factory.js +0 -0
  125. /package/{app → src}/commands/discipline.js +0 -0
  126. /package/{app → src}/commands/index.js +0 -0
  127. /package/{app → src}/commands/init.js +0 -0
  128. /package/{app → src}/commands/interview.js +0 -0
  129. /package/{app → src}/commands/progress.js +0 -0
  130. /package/{app → src}/commands/questions.js +0 -0
  131. /package/{app → src}/commands/stage.js +0 -0
  132. /package/{app → src}/commands/tool.js +0 -0
  133. /package/{app → src}/components/action-buttons.js +0 -0
  134. /package/{app → src}/components/behaviour-profile.js +0 -0
  135. /package/{app → src}/components/builder.js +0 -0
  136. /package/{app → src}/components/card.js +0 -0
  137. /package/{app → src}/components/code-display.js +0 -0
  138. /package/{app → src}/components/error-page.js +0 -0
  139. /package/{app → src}/components/grid.js +0 -0
  140. /package/{app → src}/components/list.js +0 -0
  141. /package/{app → src}/components/markdown-textarea.js +0 -0
  142. /package/{app → src}/components/modifier-table.js +0 -0
  143. /package/{app → src}/components/nav.js +0 -0
  144. /package/{app → src}/components/progression-table.js +0 -0
  145. /package/{app → src}/components/radar-chart.js +0 -0
  146. /package/{app → src}/css/base.css +0 -0
  147. /package/{app → src}/css/bundles/app.css +0 -0
  148. /package/{app → src}/css/bundles/handout.css +0 -0
  149. /package/{app → src}/css/bundles/slides.css +0 -0
  150. /package/{app → src}/css/components/badges.css +0 -0
  151. /package/{app → src}/css/components/buttons.css +0 -0
  152. /package/{app → src}/css/components/forms.css +0 -0
  153. /package/{app → src}/css/components/layout.css +0 -0
  154. /package/{app → src}/css/components/nav.css +0 -0
  155. /package/{app → src}/css/components/progress.css +0 -0
  156. /package/{app → src}/css/components/states.css +0 -0
  157. /package/{app → src}/css/components/surfaces.css +0 -0
  158. /package/{app → src}/css/components/tables.css +0 -0
  159. /package/{app → src}/css/components/typography.css +0 -0
  160. /package/{app → src}/css/components/utilities.css +0 -0
  161. /package/{app → src}/css/pages/agent-builder.css +0 -0
  162. /package/{app → src}/css/pages/assessment-results.css +0 -0
  163. /package/{app → src}/css/pages/detail.css +0 -0
  164. /package/{app → src}/css/pages/interview-builder.css +0 -0
  165. /package/{app → src}/css/pages/job-builder.css +0 -0
  166. /package/{app → src}/css/pages/landing.css +0 -0
  167. /package/{app → src}/css/pages/lifecycle.css +0 -0
  168. /package/{app → src}/css/pages/progress-builder.css +0 -0
  169. /package/{app → src}/css/pages/self-assessment.css +0 -0
  170. /package/{app → src}/css/reset.css +0 -0
  171. /package/{app → src}/css/tokens.css +0 -0
  172. /package/{app → src}/css/views/handout.css +0 -0
  173. /package/{app → src}/css/views/print.css +0 -0
  174. /package/{app → src}/css/views/slide-animations.css +0 -0
  175. /package/{app → src}/css/views/slide-base.css +0 -0
  176. /package/{app → src}/css/views/slide-sections.css +0 -0
  177. /package/{app → src}/css/views/slide-tables.css +0 -0
  178. /package/{app → src}/formatters/agent/dom.js +0 -0
  179. /package/{app → src}/formatters/agent/profile.js +0 -0
  180. /package/{app → src}/formatters/agent/skill.js +0 -0
  181. /package/{app → src}/formatters/behaviour/markdown.js +0 -0
  182. /package/{app → src}/formatters/behaviour/shared.js +0 -0
  183. /package/{app → src}/formatters/discipline/markdown.js +0 -0
  184. /package/{app → src}/formatters/discipline/shared.js +0 -0
  185. /package/{app → src}/formatters/driver/shared.js +0 -0
  186. /package/{app → src}/formatters/grade/shared.js +0 -0
  187. /package/{app → src}/formatters/index.js +0 -0
  188. /package/{app → src}/formatters/job/dom.js +0 -0
  189. /package/{app → src}/formatters/progress/dom.js +0 -0
  190. /package/{app → src}/formatters/progress/markdown.js +0 -0
  191. /package/{app → src}/formatters/questions/json.js +0 -0
  192. /package/{app → src}/formatters/questions/markdown.js +0 -0
  193. /package/{app → src}/formatters/questions/shared.js +0 -0
  194. /package/{app → src}/formatters/questions/yaml.js +0 -0
  195. /package/{app → src}/formatters/shared.js +0 -0
  196. /package/{app → src}/formatters/stage/dom.js +0 -0
  197. /package/{app → src}/formatters/stage/index.js +0 -0
  198. /package/{app → src}/formatters/stage/shared.js +0 -0
  199. /package/{app → src}/formatters/tool/shared.js +0 -0
  200. /package/{app → src}/lib/cli-output.js +0 -0
  201. /package/{app → src}/lib/error-boundary.js +0 -0
  202. /package/{app → src}/lib/errors.js +0 -0
  203. /package/{app → src}/lib/form-controls.js +0 -0
  204. /package/{app → src}/lib/markdown.js +0 -0
  205. /package/{app → src}/lib/radar.js +0 -0
  206. /package/{app → src}/lib/reactive.js +0 -0
  207. /package/{app → src}/lib/router-core.js +0 -0
  208. /package/{app → src}/lib/router-pages.js +0 -0
  209. /package/{app → src}/lib/router-slides.js +0 -0
  210. /package/{app → src}/lib/state.js +0 -0
  211. /package/{app → src}/lib/template-loader.js +0 -0
  212. /package/{app → src}/lib/utils.js +0 -0
  213. /package/{app → src}/lib/yaml-loader.js +0 -0
  214. /package/{app → src}/main.js +0 -0
  215. /package/{app → src}/pages/behaviour.js +0 -0
  216. /package/{app → src}/pages/discipline.js +0 -0
  217. /package/{app → src}/pages/driver.js +0 -0
  218. /package/{app → src}/pages/grade.js +0 -0
  219. /package/{app → src}/pages/interview-builder.js +0 -0
  220. /package/{app → src}/pages/progress-builder.js +0 -0
  221. /package/{app → src}/pages/progress.js +0 -0
  222. /package/{app → src}/pages/track.js +0 -0
  223. /package/{app → src}/slides/behaviour.js +0 -0
  224. /package/{app → src}/slides/chapter.js +0 -0
  225. /package/{app → src}/slides/discipline.js +0 -0
  226. /package/{app → src}/slides/driver.js +0 -0
  227. /package/{app → src}/slides/grade.js +0 -0
  228. /package/{app → src}/slides/interview.js +0 -0
  229. /package/{app → src}/slides/progress.js +0 -0
  230. /package/{app → src}/slides/skill.js +0 -0
  231. /package/{app → src}/slides/track.js +0 -0
  232. /package/{app → src}/types.js +0 -0
package/README.md CHANGED
@@ -1,104 +1,67 @@
1
- # Engineering Pathway
1
+ # @forwardimpact/pathway
2
2
 
3
- A unified framework for human and AI collaboration in engineering. Define roles,
4
- track skills and behaviours, build career paths, and generate AI coding
5
- agents—all from the same coherent foundation.
3
+ Career progression web app and CLI for exploring roles and generating agents.
6
4
 
7
- ## Quick Start
8
-
9
- ### Install as a Package
10
-
11
- ```sh
12
- # Create a new project
13
- mkdir my-org-pathway && cd my-org-pathway
14
- npm init -y
15
- npm install @forwardimpact/pathway
5
+ ## Role in the Vision
16
6
 
17
- # Initialize with example data
18
- npx pathway init
7
+ Pathway is the primary interface for interacting with engineering competency
8
+ data. It provides tools for browsing career paths, generating job descriptions,
9
+ creating AI agent profiles, and preparing interviews—all from a unified web
10
+ experience and command line.
19
11
 
20
- # Validate data
21
- npx pathway --validate
12
+ ## What It Does
22
13
 
23
- # Start web app
24
- npx pathway serve
25
- ```
14
+ - **Web application** — Interactive browser for jobs, skills, and career paths
15
+ - **CLI tools** — Command-line access to all functionality
16
+ - **Agent generation** — Create VS Code Custom Agent profiles (`.agent.md`)
17
+ - **Skill generation** — Generate Agent Skills files (`SKILL.md`)
18
+ - **Interview prep** — Build interview question sets by role
19
+ - **Static site** — Export everything as a static site
26
20
 
27
- Open http://localhost:3000 to explore jobs, skills, and behaviours.
21
+ ## Quick Start
28
22
 
29
- ### For Development
23
+ ```sh
24
+ # Start the web app
25
+ npx fit-pathway serve
30
26
 
31
- Clone the repository and run locally:
27
+ # Browse entities
28
+ npx fit-pathway skill --list
29
+ npx fit-pathway job software_engineering senior --track=platform
32
30
 
33
- ```sh
34
- git clone https://github.com/forwardimpact/pathway.git
35
- cd pathway
36
- npm install
37
- npm start
31
+ # Generate agent profiles
32
+ npx fit-pathway agent software_engineering --track=platform --output=./.github/agents
38
33
  ```
39
34
 
40
- ## Customization
35
+ ## CLI Commands
41
36
 
42
- Edit files in `./data/` to match your organization:
37
+ | Command | Description |
38
+ | ----------- | ---------------------------- |
39
+ | `serve` | Start web server |
40
+ | `site` | Generate static site |
41
+ | `init` | Create data directory |
42
+ | `skill` | Browse skills |
43
+ | `behaviour` | Browse behaviours |
44
+ | `job` | Generate job definitions |
45
+ | `agent` | Generate agent profiles |
46
+ | `interview` | Generate interview questions |
47
+ | `progress` | Analyze career progression |
48
+ | `questions` | Browse interview questions |
43
49
 
44
- - `grades.yaml` Career levels
45
- - `disciplines/*.yaml` — Engineering disciplines
46
- - `tracks/*.yaml` — Role tracks (platform, frontend, etc.)
47
- - `skills/*.yaml` — Technical skills with level descriptions
48
- - `behaviours/*.yaml` — Behavioural expectations
50
+ Use `--help` with any command for full options.
49
51
 
50
- ## CLI Reference
52
+ ## Web App Features
51
53
 
52
- ```sh
53
- # Getting started
54
- npx pathway init # Create ./data/ with examples
55
- npx pathway serve --port=8080 # Serve web app
56
-
57
- # Browse data
58
- npx pathway skill # Summary of all skills
59
- npx pathway skill --list # Skill IDs for piping
60
- npx pathway job software_engineering platform senior
61
-
62
- # Generate outputs
63
- npx pathway interview software_engineering platform L4
64
- npx pathway agent software_engineering platform --output=./.github/agents
65
-
66
- # Validation
67
- npx pathway --validate # Validate all data files
68
- npx pathway --help # Full command reference
69
- ```
54
+ - **Job Builder** — Select discipline, track, and grade to explore roles
55
+ - **Skill Browser** — View all skills with level descriptions
56
+ - **Career Progression** Compare grades and identify growth areas
57
+ - **Interview Prep** Generate role-specific question sets
58
+ - **Agent Preview** — Preview generated agent profiles
70
59
 
71
- ## API Usage
60
+ ## Package Exports
72
61
 
73
62
  ```javascript
74
- import { loadAllData } from "@forwardimpact/pathway";
75
- import { deriveJob } from "@forwardimpact/pathway/derivation";
76
-
77
- const data = await loadAllData("./data");
78
- const job = deriveJob({
79
- discipline: data.disciplines[0],
80
- track: data.tracks[0],
81
- grade: data.grades[0],
82
- skills: data.skills,
83
- behaviours: data.behaviours,
84
- });
63
+ import { formatSkillForMarkdown } from "@forwardimpact/pathway/formatters";
64
+ import { runCommand } from "@forwardimpact/pathway/commands";
85
65
  ```
86
66
 
87
- ## Documentation
88
-
89
- 1. [Overview](docs/index.md) — Overview of all topics
90
- 2. [Core Model](docs/model.md) — Disciplines, Tracks, Grades, Skills,
91
- Behaviours, Capabilities, Drivers, and Job Derivation
92
- 3. [Lifecycle](docs/lifecycle.md) — Stages, handoffs, and checklists (applies to
93
- both humans and agents)
94
- 4. [Agents](docs/agents.md) — Agent profile derivation, SKILL.md format, and VS
95
- Code integration
96
- 5. [Reference](docs/reference.md) — File organization, templates, and CLI usage
97
-
98
- ## Development
99
-
100
- ```sh
101
- npm run check # Format, lint, and test
102
- npm run validate # Validate YAML data files
103
- npm run test:e2e # Run end-to-end tests
104
- ```
67
+ See the [documentation](../../docs/pathway/index.md) for usage details.
@@ -6,7 +6,7 @@
6
6
  * interview questions, career progression analysis, and AI agent configurations.
7
7
  *
8
8
  * Usage:
9
- * npx pathway <command> [options]
9
+ * npx fit-pathway <command> [options]
10
10
  *
11
11
  * Commands:
12
12
  * discipline [<id>] Show disciplines
@@ -25,40 +25,36 @@
25
25
  *
26
26
  * Global Options:
27
27
  * --list Output IDs only (for piping)
28
- * --validate Run validation checks
29
28
  * --json Output as JSON
30
29
  * --help Show help
30
+ *
31
+ * Validation (moved to fit-schema):
32
+ * npx fit-schema validate
33
+ * npx fit-schema generate-index
31
34
  */
32
35
 
33
- import { fileURLToPath } from "url";
34
- import { dirname, join, resolve } from "path";
36
+ import { join, resolve } from "path";
35
37
  import { existsSync } from "fs";
36
- import { loadAllData } from "../app/model/loader.js";
37
- import { generateAllIndexes } from "../app/model/index-generator.js";
38
- import { formatError } from "../app/lib/cli-output.js";
39
- import { runSchemaValidation } from "../app/model/schema-validation.js";
38
+ import { loadAllData } from "@forwardimpact/schema/loader";
39
+ import { formatError } from "../src/lib/cli-output.js";
40
40
 
41
41
  // Import command handlers
42
- import { runDisciplineCommand } from "../app/commands/discipline.js";
43
- import { runGradeCommand } from "../app/commands/grade.js";
44
- import { runTrackCommand } from "../app/commands/track.js";
45
- import { runBehaviourCommand } from "../app/commands/behaviour.js";
46
- import { runSkillCommand } from "../app/commands/skill.js";
47
- import { runDriverCommand } from "../app/commands/driver.js";
48
- import { runStageCommand } from "../app/commands/stage.js";
49
- import { runToolCommand } from "../app/commands/tool.js";
50
- import { runJobCommand } from "../app/commands/job.js";
51
- import { runInterviewCommand } from "../app/commands/interview.js";
52
- import { runProgressCommand } from "../app/commands/progress.js";
53
- import { runQuestionsCommand } from "../app/commands/questions.js";
54
- import { runAgentCommand } from "../app/commands/agent.js";
55
- import { runServeCommand } from "../app/commands/serve.js";
56
- import { runInitCommand } from "../app/commands/init.js";
57
- import { runSiteCommand } from "../app/commands/site.js";
58
-
59
- const __filename = fileURLToPath(import.meta.url);
60
- const __dirname = dirname(__filename);
61
- const rootDir = join(__dirname, "..");
42
+ import { runDisciplineCommand } from "../src/commands/discipline.js";
43
+ import { runGradeCommand } from "../src/commands/grade.js";
44
+ import { runTrackCommand } from "../src/commands/track.js";
45
+ import { runBehaviourCommand } from "../src/commands/behaviour.js";
46
+ import { runSkillCommand } from "../src/commands/skill.js";
47
+ import { runDriverCommand } from "../src/commands/driver.js";
48
+ import { runStageCommand } from "../src/commands/stage.js";
49
+ import { runToolCommand } from "../src/commands/tool.js";
50
+ import { runJobCommand } from "../src/commands/job.js";
51
+ import { runInterviewCommand } from "../src/commands/interview.js";
52
+ import { runProgressCommand } from "../src/commands/progress.js";
53
+ import { runQuestionsCommand } from "../src/commands/questions.js";
54
+ import { runAgentCommand } from "../src/commands/agent.js";
55
+ import { runServeCommand } from "../src/commands/serve.js";
56
+ import { runInitCommand } from "../src/commands/init.js";
57
+ import { runSiteCommand } from "../src/commands/site.js";
62
58
 
63
59
  const COMMANDS = {
64
60
  discipline: runDisciplineCommand,
@@ -80,9 +76,11 @@ const HELP_TEXT = `
80
76
  Engineering Pathway CLI
81
77
 
82
78
  Usage:
83
- npx pathway <command> [options]
84
- npx pathway --validate Run full data validation
85
- npx pathway --generate-index Generate browser index files
79
+ npx fit-pathway <command> [options]
80
+
81
+ Validation (use fit-schema instead):
82
+ npx fit-schema validate Run full data validation
83
+ npx fit-schema generate-index Generate browser index files
86
84
 
87
85
  Getting Started:
88
86
  init Create ./data/ with example data
@@ -111,8 +109,6 @@ Composite Commands:
111
109
 
112
110
  Global Options:
113
111
  --list Output IDs only (for piping to other commands)
114
- --validate Run validation checks
115
- --generate-index Generate _index.yaml files for browser loading
116
112
  --json Output as JSON
117
113
  --data=PATH Path to data directory (default: ./data or examples/)
118
114
  --help Show this help message
@@ -133,26 +129,25 @@ Agent Options:
133
129
  --all-stages Generate all stage agents (default)
134
130
 
135
131
  Examples:
136
- npx pathway skill # Summary of all skills
137
- npx pathway skill --list # Skill IDs for piping
138
- npx pathway skill ai_evaluation # Detail view
139
- npx pathway skill architecture_design --agent # Agent SKILL.md output
140
-
141
- npx pathway tool # Summary of all tools
142
- npx pathway tool --list # Tool names for piping
143
- npx pathway tool DuckDB # Tool detail with skill usages
144
-
145
- npx pathway job # Summary of valid combinations
146
- npx pathway job --list # All combinations for piping
147
- npx pathway job software_engineering L4
148
- npx pathway job software_engineering L4 --track=platform
149
- npx pathway job se L3 --track=platform --checklist=code
150
-
151
- npx pathway questions --level=practitioner
152
- npx pathway questions --stats
153
-
154
- npx pathway agent software_engineering --track=platform --output=./agents
155
- npx pathway --validate # Validate all data
132
+ npx fit-pathway skill # Summary of all skills
133
+ npx fit-pathway skill --list # Skill IDs for piping
134
+ npx fit-pathway skill ai_evaluation # Detail view
135
+ npx fit-pathway skill architecture_design --agent # Agent SKILL.md output
136
+
137
+ npx fit-pathway tool # Summary of all tools
138
+ npx fit-pathway tool --list # Tool names for piping
139
+ npx fit-pathway tool DuckDB # Tool detail with skill usages
140
+
141
+ npx fit-pathway job # Summary of valid combinations
142
+ npx fit-pathway job --list # All combinations for piping
143
+ npx fit-pathway job software_engineering L4
144
+ npx fit-pathway job software_engineering L4 --track=platform
145
+ npx fit-pathway job se L3 --track=platform --checklist=code
146
+
147
+ npx fit-pathway questions --level=practitioner
148
+ npx fit-pathway questions --stats
149
+
150
+ npx fit-pathway agent software_engineering --track=platform --output=./agents
156
151
  `;
157
152
 
158
153
  /**
@@ -167,8 +162,6 @@ function parseArgs(args) {
167
162
  list: false,
168
163
  json: false,
169
164
  help: false,
170
- validate: false,
171
- generateIndex: false,
172
165
  type: "full",
173
166
  compare: null,
174
167
  data: null,
@@ -204,10 +197,6 @@ function parseArgs(args) {
204
197
  result.list = true;
205
198
  } else if (arg === "--json") {
206
199
  result.json = true;
207
- } else if (arg === "--validate") {
208
- result.validate = true;
209
- } else if (arg === "--generate-index") {
210
- result.generateIndex = true;
211
200
  } else if (arg.startsWith("--type=")) {
212
201
  result.type = arg.slice(7);
213
202
  } else if (arg.startsWith("--compare=")) {
@@ -269,85 +258,14 @@ function printHelp() {
269
258
  console.log(HELP_TEXT);
270
259
  }
271
260
 
272
- /**
273
- * Run full data validation using JSON schemas
274
- * @param {string} dataDir - Path to data directory
275
- */
276
- async function runFullValidation(dataDir) {
277
- console.log(`\n🔍 Validating data in: ${dataDir}\n`);
278
-
279
- let hasErrors = false;
280
-
281
- // Load data for referential integrity checking (without old validation)
282
- const data = await loadAllData(dataDir, {
283
- validate: false,
284
- throwOnError: false,
285
- });
286
-
287
- // Run schema validation + referential integrity
288
- const result = await runSchemaValidation(dataDir, data);
289
-
290
- if (result.valid) {
291
- console.log("✅ Schema validation passed");
292
- } else {
293
- console.log("❌ Schema validation failed");
294
- hasErrors = true;
295
- for (const e of result.errors) {
296
- console.log(
297
- ` - [${e.type}] ${e.message}${e.path ? ` (${e.path})` : ""}`,
298
- );
299
- }
300
- }
301
-
302
- if (result.warnings.length > 0) {
303
- console.log("\n⚠️ Warnings:");
304
- for (const w of result.warnings) {
305
- console.log(` - [${w.type}] ${w.message}`);
306
- }
307
- }
308
-
309
- // Summary
310
- console.log("\n📊 Data Summary:");
311
- console.log(` Skills: ${data.skills?.length || 0}`);
312
- console.log(` Behaviours: ${data.behaviours?.length || 0}`);
313
- console.log(` Disciplines: ${data.disciplines?.length || 0}`);
314
- console.log(` Tracks: ${data.tracks?.length || 0}`);
315
- console.log(` Grades: ${data.grades?.length || 0}`);
316
- console.log(` Drivers: ${data.drivers?.length || 0}`);
317
- console.log(` Stages: ${data.stages?.length || 0}`);
318
- console.log("");
319
-
320
- return hasErrors ? 1 : 0;
321
- }
322
-
323
- /**
324
- * Run index generation
325
- * @param {string} dataDir - Path to data directory
326
- */
327
- async function runGenerateIndex(dataDir) {
328
- console.log(`\n📁 Generating index files in: ${dataDir}\n`);
329
-
330
- const results = await generateAllIndexes(dataDir);
331
-
332
- for (const [dir, files] of Object.entries(results)) {
333
- if (files.error) {
334
- console.log(`❌ ${dir}: ${files.error}`);
335
- } else {
336
- console.log(`✅ ${dir}/_index.yaml (${files.length} files)`);
337
- }
338
- }
339
-
340
- console.log("\n✨ Index generation complete\n");
341
- return 0;
342
- }
343
-
344
261
  /**
345
262
  * Resolve the data directory path.
346
263
  * Resolution order:
347
264
  * 1. --data=<path> flag (explicit override)
348
265
  * 2. PATHWAY_DATA environment variable
349
266
  * 3. ./data/ relative to current working directory
350
- * 4. Package examples (for demo/testing)
267
+ * 4. ./examples/ relative to current working directory
268
+ * 5. apps/schema/examples/ for monorepo development
351
269
  *
352
270
  * @param {Object} options - Parsed command options
353
271
  * @returns {string} Resolved absolute path to data directory
@@ -363,16 +281,22 @@ function resolveDataPath(options) {
363
281
  return resolve(process.env.PATHWAY_DATA);
364
282
  }
365
283
 
366
- // 3. Current working directory
284
+ // 3. Current working directory ./data/
367
285
  const cwdData = join(process.cwd(), "data");
368
286
  if (existsSync(cwdData)) {
369
287
  return cwdData;
370
288
  }
371
289
 
372
- // 4. Package examples (for demo/testing)
373
- const examplesData = join(rootDir, "examples");
374
- if (existsSync(examplesData)) {
375
- return examplesData;
290
+ // 4. Current working directory ./examples/
291
+ const cwdExamples = join(process.cwd(), "examples");
292
+ if (existsSync(cwdExamples)) {
293
+ return cwdExamples;
294
+ }
295
+
296
+ // 5. Monorepo: apps/schema/examples/
297
+ const schemaExamples = join(process.cwd(), "apps/schema/examples");
298
+ if (existsSync(schemaExamples)) {
299
+ return schemaExamples;
376
300
  }
377
301
 
378
302
  throw new Error(
@@ -392,21 +316,7 @@ async function main() {
392
316
  process.exit(0);
393
317
  }
394
318
 
395
- const dataDir = resolveDataPath(options);
396
-
397
- // Handle global --generate-index (no command)
398
- if (options.generateIndex && !options.command) {
399
- const exitCode = await runGenerateIndex(dataDir);
400
- process.exit(exitCode);
401
- }
402
-
403
- // Handle global --validate (no command)
404
- if (options.validate && !options.command) {
405
- const exitCode = await runFullValidation(dataDir);
406
- process.exit(exitCode);
407
- }
408
-
409
- // No command and no flags: show help
319
+ // No command: show help
410
320
  if (!options.command) {
411
321
  printHelp();
412
322
  process.exit(0);
@@ -420,6 +330,8 @@ async function main() {
420
330
  process.exit(0);
421
331
  }
422
332
 
333
+ const dataDir = resolveDataPath(options);
334
+
423
335
  // Handle serve command (needs data directory)
424
336
  if (command === "serve") {
425
337
  await runServeCommand({ dataDir, options });
@@ -437,7 +349,7 @@ async function main() {
437
349
 
438
350
  if (!handler) {
439
351
  console.error(formatError(`Unknown command: ${command}`));
440
- console.error(`Run 'npx pathway --help' for usage.`);
352
+ console.error(`Run 'npx fit-pathway --help' for usage.`);
441
353
  process.exit(1);
442
354
  }
443
355
 
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@forwardimpact/pathway",
3
- "version": "0.5.0",
4
- "description": "Engineering Pathway framework for human and AI collaboration",
3
+ "version": "0.7.0",
4
+ "description": "Career progression web app and CLI for exploring roles and generating agents",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/forwardimpact/pathway"
8
+ "url": "https://github.com/forwardimpact/monorepo",
9
+ "directory": "apps/pathway"
9
10
  },
11
+ "homepage": "https://www.forwardimpact.team/pathway",
10
12
  "keywords": [
11
13
  "career",
12
14
  "competency",
@@ -18,57 +20,32 @@
18
20
  "engineering"
19
21
  ],
20
22
  "type": "module",
21
- "main": "app/model/loader.js",
23
+ "main": "src/index.js",
22
24
  "bin": {
23
- "pathway": "./bin/pathway.js"
25
+ "fit-pathway": "./bin/fit-pathway.js"
26
+ },
27
+ "scripts": {
28
+ "start": "node ./bin/fit-pathway.js serve",
29
+ "pathway": "node ./bin/fit-pathway.js",
30
+ "site": "node ./bin/fit-pathway.js site"
24
31
  },
25
32
  "files": [
26
33
  "bin/",
27
- "app/",
28
- "examples/",
34
+ "src/",
29
35
  "templates/"
30
36
  ],
31
37
  "exports": {
32
- ".": "./app/model/loader.js",
33
- "./derivation": "./app/model/derivation.js",
34
- "./interview": "./app/model/interview.js",
35
- "./levels": "./app/model/levels.js",
36
- "./loader": "./app/model/loader.js",
37
- "./matching": "./app/model/matching.js",
38
- "./types": "./app/model/levels.js",
39
- "./validation": "./app/model/validation.js"
40
- },
41
- "scripts": {
42
- "start": "node bin/pathway.js serve",
43
- "prestart": "npm run generate-index",
44
- "check": "npm run format && npm run lint && npm run test && npm run validate:shacl",
45
- "check:fix": "npm run format:fix && npm run lint:fix",
46
- "lint": "eslint .",
47
- "lint:fix": "eslint . --fix",
48
- "format": "prettier --check .",
49
- "format:fix": "prettier --write .",
50
- "test": "find ./tests -name '*.test.js' | xargs node --test",
51
- "test:e2e": "npx playwright test",
52
- "validate": "node bin/pathway.js --validate",
53
- "validate:shacl": "node scripts/validate-shacl.js",
54
- "generate-index": "node bin/pathway.js --generate-index",
55
- "pathway": "node bin/pathway.js",
56
- "demo": "node scripts/demo.js"
38
+ ".": "./src/index.js",
39
+ "./formatters": "./src/formatters/index.js",
40
+ "./commands": "./src/commands/index.js"
57
41
  },
58
42
  "dependencies": {
59
- "ajv": "^8.17.1",
60
- "ajv-formats": "^3.0.1",
43
+ "@forwardimpact/schema": "^0.2.0",
44
+ "@forwardimpact/model": "^0.2.0",
61
45
  "mustache": "^4.2.0",
62
46
  "simple-icons": "^16.7.0",
63
47
  "yaml": "^2.3.4"
64
48
  },
65
- "devDependencies": {
66
- "@playwright/test": "^1.49.0",
67
- "eslint": "^9.39.1",
68
- "eslint-config-prettier": "^10.1.8",
69
- "n3": "^2.0.1",
70
- "prettier": "^3.7.4"
71
- },
72
49
  "engines": {
73
50
  "node": ">=18.0.0"
74
51
  }
@@ -25,7 +25,10 @@ import { writeFile, mkdir, readFile } from "fs/promises";
25
25
  import { join, dirname } from "path";
26
26
  import { existsSync } from "fs";
27
27
  import { stringify as stringifyYaml } from "yaml";
28
- import { loadAgentData, loadSkillsWithAgentData } from "../model/loader.js";
28
+ import {
29
+ loadAgentData,
30
+ loadSkillsWithAgentData,
31
+ } from "@forwardimpact/schema/loader";
29
32
  import {
30
33
  generateStageAgentProfile,
31
34
  validateAgentProfile,
@@ -33,7 +36,7 @@ import {
33
36
  deriveReferenceGrade,
34
37
  deriveAgentSkills,
35
38
  generateSkillMd,
36
- } from "../model/agent.js";
39
+ } from "@forwardimpact/model/agent";
37
40
  import { formatAgentProfile } from "../formatters/agent/profile.js";
38
41
  import { formatAgentSkill } from "../formatters/agent/skill.js";
39
42
  import { formatError, formatSuccess } from "../lib/cli-output.js";
@@ -18,7 +18,7 @@ import {
18
18
  formatSubheader,
19
19
  formatBullet,
20
20
  } from "../lib/cli-output.js";
21
- import { getConceptEmoji } from "../model/levels.js";
21
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
22
22
 
23
23
  /**
24
24
  * Format driver summary output
@@ -13,7 +13,7 @@
13
13
  import { createEntityCommand } from "./command-factory.js";
14
14
  import { gradeToMarkdown } from "../formatters/grade/markdown.js";
15
15
  import { formatTable } from "../lib/cli-output.js";
16
- import { getConceptEmoji } from "../model/levels.js";
16
+ import { getConceptEmoji } from "@forwardimpact/schema/levels";
17
17
  import { capitalize } from "../formatters/shared.js";
18
18
 
19
19
  /**
@@ -12,14 +12,14 @@
12
12
  * npx pathway job --validate # Validation checks
13
13
  */
14
14
 
15
- import { prepareJobDetail } from "../model/job.js";
15
+ import { prepareJobDetail } from "@forwardimpact/model/job";
16
16
  import { jobToMarkdown } from "../formatters/job/markdown.js";
17
- import { generateAllJobs } from "../model/derivation.js";
17
+ import { generateAllJobs } from "@forwardimpact/model/derivation";
18
18
  import { formatTable } from "../lib/cli-output.js";
19
19
  import {
20
20
  deriveChecklist,
21
21
  formatChecklistMarkdown,
22
- } from "../model/checklist.js";
22
+ } from "@forwardimpact/model/checklist";
23
23
  import { loadJobTemplate } from "../lib/template-loader.js";
24
24
 
25
25
  /**
@@ -9,14 +9,30 @@ import { createServer } from "http";
9
9
  import { readFile, stat } from "fs/promises";
10
10
  import { join, extname, dirname } from "path";
11
11
  import { fileURLToPath } from "url";
12
- import { generateAllIndexes } from "../model/index-generator.js";
13
- import { loadFrameworkConfig } from "../model/loader.js";
12
+ import { generateAllIndexes } from "@forwardimpact/schema/index-generator";
13
+ import { loadFrameworkConfig } from "@forwardimpact/schema/loader";
14
14
 
15
15
  const __filename = fileURLToPath(import.meta.url);
16
16
  const __dirname = dirname(__filename);
17
17
  const publicDir = join(__dirname, "..");
18
18
  const rootDir = join(__dirname, "../..");
19
19
 
20
+ /**
21
+ * Resolve package directory using Node's module resolution.
22
+ * Works in both monorepo (development) and installed (production) contexts.
23
+ * @param {string} packageName - Package specifier (e.g., '@forwardimpact/schema')
24
+ * @returns {string} Absolute path to package lib directory
25
+ */
26
+ function resolvePackageLib(packageName) {
27
+ // import.meta.resolve returns file:// URL to package's main entry (lib/index.js)
28
+ const mainUrl = import.meta.resolve(packageName);
29
+ // Convert to path and get lib directory
30
+ return dirname(fileURLToPath(mainUrl));
31
+ }
32
+
33
+ const schemaLibDir = resolvePackageLib("@forwardimpact/schema");
34
+ const modelLibDir = resolvePackageLib("@forwardimpact/model");
35
+
20
36
  const MIME_TYPES = {
21
37
  ".html": "text/html; charset=utf-8",
22
38
  ".css": "text/css; charset=utf-8",
@@ -118,6 +134,12 @@ export async function runServeCommand({ dataDir, options }) {
118
134
  } else if (pathname.startsWith("/templates/")) {
119
135
  // Serve from templates directory
120
136
  filePath = join(rootDir, pathname);
137
+ } else if (pathname.startsWith("/schema/lib/")) {
138
+ // Serve @forwardimpact/schema package files (resolved via Node module resolution)
139
+ filePath = join(schemaLibDir, pathname.slice(12));
140
+ } else if (pathname.startsWith("/model/lib/")) {
141
+ // Serve @forwardimpact/model package files (resolved via Node module resolution)
142
+ filePath = join(modelLibDir, pathname.slice(11));
121
143
  } else if (pathname === "/" || pathname === "") {
122
144
  // Serve index.html for root
123
145
  filePath = join(publicDir, "index.html");