@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.
- package/README.md +47 -84
- package/bin/{pathway.js → fit-pathway.js} +65 -153
- package/package.json +18 -41
- package/{app → src}/commands/agent.js +5 -2
- package/{app → src}/commands/driver.js +1 -1
- package/{app → src}/commands/grade.js +1 -1
- package/{app → src}/commands/job.js +3 -3
- package/{app → src}/commands/serve.js +24 -2
- package/{app → src}/commands/site.js +2 -2
- package/{app → src}/commands/skill.js +2 -2
- package/{app → src}/commands/track.js +1 -1
- package/{app → src}/components/checklist.js +1 -1
- package/{app → src}/components/comparison-radar.js +1 -1
- package/{app → src}/components/detail.js +1 -1
- package/{app → src}/components/skill-matrix.js +1 -1
- package/{app → src}/formatters/behaviour/dom.js +1 -1
- package/{app → src}/formatters/behaviour/microdata.js +1 -1
- package/{app → src}/formatters/discipline/dom.js +1 -1
- package/{app → src}/formatters/discipline/microdata.js +1 -1
- package/{app → src}/formatters/driver/dom.js +1 -1
- package/{app → src}/formatters/driver/microdata.js +1 -1
- package/{app → src}/formatters/grade/dom.js +1 -1
- package/{app → src}/formatters/grade/markdown.js +1 -1
- package/{app → src}/formatters/grade/microdata.js +1 -1
- package/{app → src}/formatters/interview/dom.js +1 -1
- package/{app → src}/formatters/interview/markdown.js +1 -1
- package/{app → src}/formatters/interview/shared.js +3 -3
- package/{app → src}/formatters/job/description.js +1 -1
- package/{app → src}/formatters/job/markdown.js +1 -1
- package/{app → src}/formatters/json-ld.js +2 -2
- package/{app → src}/formatters/microdata-shared.js +2 -2
- package/{app → src}/formatters/progress/shared.js +3 -3
- package/{app → src}/formatters/skill/dom.js +1 -1
- package/{app → src}/formatters/skill/markdown.js +1 -1
- package/{app → src}/formatters/skill/microdata.js +1 -1
- package/{app → src}/formatters/skill/shared.js +2 -2
- package/{app → src}/formatters/stage/microdata.js +1 -1
- package/{app → src}/formatters/track/dom.js +1 -1
- package/{app → src}/formatters/track/markdown.js +1 -1
- package/{app → src}/formatters/track/microdata.js +1 -1
- package/{app → src}/formatters/track/shared.js +4 -1
- package/{app → src}/handout-main.js +4 -1
- package/src/handout.html +43 -0
- package/{app → src}/index.html +16 -1
- package/{app → src}/lib/card-mappers.js +1 -1
- package/{app → src}/lib/job-cache.js +1 -1
- package/{app → src}/lib/render.js +1 -1
- package/{app → src}/pages/agent-builder.js +1 -1
- package/{app → src}/pages/assessment-results.js +1 -1
- package/{app → src}/pages/interview.js +1 -1
- package/{app → src}/pages/job-builder.js +1 -1
- package/{app → src}/pages/job.js +1 -1
- package/{app → src}/pages/landing.js +4 -1
- package/{app → src}/pages/self-assessment.js +1 -1
- package/{app → src}/pages/skill.js +1 -1
- package/{app → src}/pages/stage.js +1 -1
- package/{app → src}/pages/tool.js +1 -1
- package/{app → src}/slide-main.js +1 -1
- package/{app → src}/slides/index.js +2 -2
- package/{app → src}/slides/job.js +1 -1
- package/{app → src}/slides/overview.js +1 -1
- package/{app → src}/slides.html +16 -1
- package/templates/agent.template.md +27 -26
- package/templates/job.template.md +11 -17
- package/templates/skill.template.md +15 -21
- package/app/handout.html +0 -28
- package/app/model/agent.js +0 -754
- package/app/model/checklist.js +0 -103
- package/app/model/derivation.js +0 -766
- package/app/model/index-generator.js +0 -65
- package/app/model/interview.js +0 -539
- package/app/model/job.js +0 -228
- package/app/model/levels.js +0 -601
- package/app/model/loader.js +0 -599
- package/app/model/matching.js +0 -888
- package/app/model/modifiers.js +0 -158
- package/app/model/profile.js +0 -259
- package/app/model/progression.js +0 -507
- package/app/model/schema-validation.js +0 -438
- package/app/model/validation.js +0 -2130
- package/examples/behaviours/_index.yaml +0 -8
- package/examples/behaviours/outcome_ownership.yaml +0 -43
- package/examples/behaviours/polymathic_knowledge.yaml +0 -41
- package/examples/behaviours/precise_communication.yaml +0 -39
- package/examples/behaviours/relentless_curiosity.yaml +0 -37
- package/examples/behaviours/systems_thinking.yaml +0 -40
- package/examples/capabilities/_index.yaml +0 -8
- package/examples/capabilities/business.yaml +0 -189
- package/examples/capabilities/delivery.yaml +0 -305
- package/examples/capabilities/people.yaml +0 -68
- package/examples/capabilities/reliability.yaml +0 -414
- package/examples/capabilities/scale.yaml +0 -378
- package/examples/copilot-setup-steps.yaml +0 -25
- package/examples/devcontainer.yaml +0 -21
- package/examples/disciplines/_index.yaml +0 -6
- package/examples/disciplines/data_engineering.yaml +0 -78
- package/examples/disciplines/engineering_management.yaml +0 -63
- package/examples/disciplines/software_engineering.yaml +0 -78
- package/examples/drivers.yaml +0 -202
- package/examples/framework.yaml +0 -69
- package/examples/grades.yaml +0 -115
- package/examples/questions/behaviours/outcome_ownership.yaml +0 -51
- package/examples/questions/behaviours/polymathic_knowledge.yaml +0 -47
- package/examples/questions/behaviours/precise_communication.yaml +0 -54
- package/examples/questions/behaviours/relentless_curiosity.yaml +0 -50
- package/examples/questions/behaviours/systems_thinking.yaml +0 -52
- package/examples/questions/skills/architecture_design.yaml +0 -53
- package/examples/questions/skills/cloud_platforms.yaml +0 -47
- package/examples/questions/skills/code_quality.yaml +0 -48
- package/examples/questions/skills/data_modeling.yaml +0 -45
- package/examples/questions/skills/devops.yaml +0 -46
- package/examples/questions/skills/full_stack_development.yaml +0 -47
- package/examples/questions/skills/sre_practices.yaml +0 -43
- package/examples/questions/skills/stakeholder_management.yaml +0 -48
- package/examples/questions/skills/team_collaboration.yaml +0 -42
- package/examples/questions/skills/technical_writing.yaml +0 -42
- package/examples/self-assessments.yaml +0 -64
- package/examples/stages.yaml +0 -139
- package/examples/tracks/_index.yaml +0 -5
- package/examples/tracks/platform.yaml +0 -49
- package/examples/tracks/sre.yaml +0 -48
- package/examples/vscode-settings.yaml +0 -17
- /package/{app → src}/commands/behaviour.js +0 -0
- /package/{app → src}/commands/command-factory.js +0 -0
- /package/{app → src}/commands/discipline.js +0 -0
- /package/{app → src}/commands/index.js +0 -0
- /package/{app → src}/commands/init.js +0 -0
- /package/{app → src}/commands/interview.js +0 -0
- /package/{app → src}/commands/progress.js +0 -0
- /package/{app → src}/commands/questions.js +0 -0
- /package/{app → src}/commands/stage.js +0 -0
- /package/{app → src}/commands/tool.js +0 -0
- /package/{app → src}/components/action-buttons.js +0 -0
- /package/{app → src}/components/behaviour-profile.js +0 -0
- /package/{app → src}/components/builder.js +0 -0
- /package/{app → src}/components/card.js +0 -0
- /package/{app → src}/components/code-display.js +0 -0
- /package/{app → src}/components/error-page.js +0 -0
- /package/{app → src}/components/grid.js +0 -0
- /package/{app → src}/components/list.js +0 -0
- /package/{app → src}/components/markdown-textarea.js +0 -0
- /package/{app → src}/components/modifier-table.js +0 -0
- /package/{app → src}/components/nav.js +0 -0
- /package/{app → src}/components/progression-table.js +0 -0
- /package/{app → src}/components/radar-chart.js +0 -0
- /package/{app → src}/css/base.css +0 -0
- /package/{app → src}/css/bundles/app.css +0 -0
- /package/{app → src}/css/bundles/handout.css +0 -0
- /package/{app → src}/css/bundles/slides.css +0 -0
- /package/{app → src}/css/components/badges.css +0 -0
- /package/{app → src}/css/components/buttons.css +0 -0
- /package/{app → src}/css/components/forms.css +0 -0
- /package/{app → src}/css/components/layout.css +0 -0
- /package/{app → src}/css/components/nav.css +0 -0
- /package/{app → src}/css/components/progress.css +0 -0
- /package/{app → src}/css/components/states.css +0 -0
- /package/{app → src}/css/components/surfaces.css +0 -0
- /package/{app → src}/css/components/tables.css +0 -0
- /package/{app → src}/css/components/typography.css +0 -0
- /package/{app → src}/css/components/utilities.css +0 -0
- /package/{app → src}/css/pages/agent-builder.css +0 -0
- /package/{app → src}/css/pages/assessment-results.css +0 -0
- /package/{app → src}/css/pages/detail.css +0 -0
- /package/{app → src}/css/pages/interview-builder.css +0 -0
- /package/{app → src}/css/pages/job-builder.css +0 -0
- /package/{app → src}/css/pages/landing.css +0 -0
- /package/{app → src}/css/pages/lifecycle.css +0 -0
- /package/{app → src}/css/pages/progress-builder.css +0 -0
- /package/{app → src}/css/pages/self-assessment.css +0 -0
- /package/{app → src}/css/reset.css +0 -0
- /package/{app → src}/css/tokens.css +0 -0
- /package/{app → src}/css/views/handout.css +0 -0
- /package/{app → src}/css/views/print.css +0 -0
- /package/{app → src}/css/views/slide-animations.css +0 -0
- /package/{app → src}/css/views/slide-base.css +0 -0
- /package/{app → src}/css/views/slide-sections.css +0 -0
- /package/{app → src}/css/views/slide-tables.css +0 -0
- /package/{app → src}/formatters/agent/dom.js +0 -0
- /package/{app → src}/formatters/agent/profile.js +0 -0
- /package/{app → src}/formatters/agent/skill.js +0 -0
- /package/{app → src}/formatters/behaviour/markdown.js +0 -0
- /package/{app → src}/formatters/behaviour/shared.js +0 -0
- /package/{app → src}/formatters/discipline/markdown.js +0 -0
- /package/{app → src}/formatters/discipline/shared.js +0 -0
- /package/{app → src}/formatters/driver/shared.js +0 -0
- /package/{app → src}/formatters/grade/shared.js +0 -0
- /package/{app → src}/formatters/index.js +0 -0
- /package/{app → src}/formatters/job/dom.js +0 -0
- /package/{app → src}/formatters/progress/dom.js +0 -0
- /package/{app → src}/formatters/progress/markdown.js +0 -0
- /package/{app → src}/formatters/questions/json.js +0 -0
- /package/{app → src}/formatters/questions/markdown.js +0 -0
- /package/{app → src}/formatters/questions/shared.js +0 -0
- /package/{app → src}/formatters/questions/yaml.js +0 -0
- /package/{app → src}/formatters/shared.js +0 -0
- /package/{app → src}/formatters/stage/dom.js +0 -0
- /package/{app → src}/formatters/stage/index.js +0 -0
- /package/{app → src}/formatters/stage/shared.js +0 -0
- /package/{app → src}/formatters/tool/shared.js +0 -0
- /package/{app → src}/lib/cli-output.js +0 -0
- /package/{app → src}/lib/error-boundary.js +0 -0
- /package/{app → src}/lib/errors.js +0 -0
- /package/{app → src}/lib/form-controls.js +0 -0
- /package/{app → src}/lib/markdown.js +0 -0
- /package/{app → src}/lib/radar.js +0 -0
- /package/{app → src}/lib/reactive.js +0 -0
- /package/{app → src}/lib/router-core.js +0 -0
- /package/{app → src}/lib/router-pages.js +0 -0
- /package/{app → src}/lib/router-slides.js +0 -0
- /package/{app → src}/lib/state.js +0 -0
- /package/{app → src}/lib/template-loader.js +0 -0
- /package/{app → src}/lib/utils.js +0 -0
- /package/{app → src}/lib/yaml-loader.js +0 -0
- /package/{app → src}/main.js +0 -0
- /package/{app → src}/pages/behaviour.js +0 -0
- /package/{app → src}/pages/discipline.js +0 -0
- /package/{app → src}/pages/driver.js +0 -0
- /package/{app → src}/pages/grade.js +0 -0
- /package/{app → src}/pages/interview-builder.js +0 -0
- /package/{app → src}/pages/progress-builder.js +0 -0
- /package/{app → src}/pages/progress.js +0 -0
- /package/{app → src}/pages/track.js +0 -0
- /package/{app → src}/slides/behaviour.js +0 -0
- /package/{app → src}/slides/chapter.js +0 -0
- /package/{app → src}/slides/discipline.js +0 -0
- /package/{app → src}/slides/driver.js +0 -0
- /package/{app → src}/slides/grade.js +0 -0
- /package/{app → src}/slides/interview.js +0 -0
- /package/{app → src}/slides/progress.js +0 -0
- /package/{app → src}/slides/skill.js +0 -0
- /package/{app → src}/slides/track.js +0 -0
- /package/{app → src}/types.js +0 -0
package/README.md
CHANGED
|
@@ -1,104 +1,67 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @forwardimpact/pathway
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
18
|
-
|
|
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
|
-
|
|
21
|
-
npx pathway --validate
|
|
12
|
+
## What It Does
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
21
|
+
## Quick Start
|
|
28
22
|
|
|
29
|
-
|
|
23
|
+
```sh
|
|
24
|
+
# Start the web app
|
|
25
|
+
npx fit-pathway serve
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
# Browse entities
|
|
28
|
+
npx fit-pathway skill --list
|
|
29
|
+
npx fit-pathway job software_engineering senior --track=platform
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
##
|
|
35
|
+
## CLI Commands
|
|
41
36
|
|
|
42
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
52
|
+
## Web App Features
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
##
|
|
60
|
+
## Package Exports
|
|
72
61
|
|
|
73
62
|
```javascript
|
|
74
|
-
import {
|
|
75
|
-
import {
|
|
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
|
-
|
|
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 {
|
|
34
|
-
import { dirname, join, resolve } from "path";
|
|
36
|
+
import { join, resolve } from "path";
|
|
35
37
|
import { existsSync } from "fs";
|
|
36
|
-
import { loadAllData } from "
|
|
37
|
-
import {
|
|
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 "../
|
|
43
|
-
import { runGradeCommand } from "../
|
|
44
|
-
import { runTrackCommand } from "../
|
|
45
|
-
import { runBehaviourCommand } from "../
|
|
46
|
-
import { runSkillCommand } from "../
|
|
47
|
-
import { runDriverCommand } from "../
|
|
48
|
-
import { runStageCommand } from "../
|
|
49
|
-
import { runToolCommand } from "../
|
|
50
|
-
import { runJobCommand } from "../
|
|
51
|
-
import { runInterviewCommand } from "../
|
|
52
|
-
import { runProgressCommand } from "../
|
|
53
|
-
import { runQuestionsCommand } from "../
|
|
54
|
-
import { runAgentCommand } from "../
|
|
55
|
-
import { runServeCommand } from "../
|
|
56
|
-
import { runInitCommand } from "../
|
|
57
|
-
import { runSiteCommand } from "../
|
|
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
|
-
|
|
85
|
-
|
|
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.
|
|
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.
|
|
373
|
-
const
|
|
374
|
-
if (existsSync(
|
|
375
|
-
return
|
|
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
|
-
|
|
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.
|
|
4
|
-
"description": "
|
|
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/
|
|
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": "
|
|
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
|
-
"
|
|
28
|
-
"examples/",
|
|
34
|
+
"src/",
|
|
29
35
|
"templates/"
|
|
30
36
|
],
|
|
31
37
|
"exports": {
|
|
32
|
-
".": "./
|
|
33
|
-
"./
|
|
34
|
-
"./
|
|
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
|
-
"
|
|
60
|
-
"
|
|
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 {
|
|
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 "
|
|
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";
|
|
@@ -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 "
|
|
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 "
|
|
15
|
+
import { prepareJobDetail } from "@forwardimpact/model/job";
|
|
16
16
|
import { jobToMarkdown } from "../formatters/job/markdown.js";
|
|
17
|
-
import { generateAllJobs } from "
|
|
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 "
|
|
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 "
|
|
13
|
-
import { loadFrameworkConfig } from "
|
|
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");
|