@forwardimpact/pathway 0.8.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/fit-pathway.js +12 -12
- package/package.json +3 -3
- package/src/commands/{site.js → build.js} +4 -4
- package/src/commands/{serve.js → dev.js} +4 -4
- package/src/formatters/agent/profile.js +18 -3
- package/src/formatters/skill/dom.js +4 -3
- package/src/formatters/skill/markdown.js +2 -2
- package/src/formatters/toolkit/dom.js +5 -17
- package/src/lib/card-mappers.js +1 -1
- package/templates/agent.template.md +27 -20
- package/templates/skill.template.md +9 -9
package/bin/fit-pathway.js
CHANGED
|
@@ -48,9 +48,9 @@ import { runInterviewCommand } from "../src/commands/interview.js";
|
|
|
48
48
|
import { runProgressCommand } from "../src/commands/progress.js";
|
|
49
49
|
import { runQuestionsCommand } from "../src/commands/questions.js";
|
|
50
50
|
import { runAgentCommand } from "../src/commands/agent.js";
|
|
51
|
-
import {
|
|
51
|
+
import { runDevCommand } from "../src/commands/dev.js";
|
|
52
52
|
import { runInitCommand } from "../src/commands/init.js";
|
|
53
|
-
import {
|
|
53
|
+
import { runBuildCommand } from "../src/commands/build.js";
|
|
54
54
|
|
|
55
55
|
const COMMANDS = {
|
|
56
56
|
discipline: runDisciplineCommand,
|
|
@@ -85,8 +85,8 @@ GETTING STARTED
|
|
|
85
85
|
────────────────────────────────────────────────────────────────────────────────
|
|
86
86
|
|
|
87
87
|
init Create ./data/ with example data
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
dev [--port=PORT] Run live development server
|
|
89
|
+
build [--output=PATH] Generate static site to ./public/
|
|
90
90
|
|
|
91
91
|
────────────────────────────────────────────────────────────────────────────────
|
|
92
92
|
ENTITY COMMANDS
|
|
@@ -104,7 +104,7 @@ All entity commands support: summary (default), --list (IDs for piping), <id> (d
|
|
|
104
104
|
skill [<id>] Browse skills
|
|
105
105
|
--agent Output as agent SKILL.md format
|
|
106
106
|
|
|
107
|
-
tool [<name>] Browse
|
|
107
|
+
tool [<name>] Browse required tools (aggregated from skills)
|
|
108
108
|
|
|
109
109
|
────────────────────────────────────────────────────────────────────────────────
|
|
110
110
|
JOB COMMAND
|
|
@@ -400,16 +400,16 @@ async function main() {
|
|
|
400
400
|
|
|
401
401
|
const dataDir = resolveDataPath(options);
|
|
402
402
|
|
|
403
|
-
// Handle
|
|
404
|
-
if (command === "
|
|
405
|
-
await
|
|
406
|
-
//
|
|
403
|
+
// Handle dev command (needs data directory)
|
|
404
|
+
if (command === "dev") {
|
|
405
|
+
await runDevCommand({ dataDir, options });
|
|
406
|
+
// dev doesn't exit, keeps running
|
|
407
407
|
return;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
-
// Handle
|
|
411
|
-
if (command === "
|
|
412
|
-
await
|
|
410
|
+
// Handle build command (generates static site)
|
|
411
|
+
if (command === "build") {
|
|
412
|
+
await runBuildCommand({ dataDir, options });
|
|
413
413
|
process.exit(0);
|
|
414
414
|
}
|
|
415
415
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forwardimpact/pathway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Career progression web app and CLI for exploring roles and generating agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"./commands": "./src/commands/index.js"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@forwardimpact/schema": "^0.
|
|
44
|
-
"@forwardimpact/model": "^0.
|
|
43
|
+
"@forwardimpact/schema": "^0.4.0",
|
|
44
|
+
"@forwardimpact/model": "^0.5.0",
|
|
45
45
|
"mustache": "^4.2.0",
|
|
46
46
|
"simple-icons": "^16.7.0",
|
|
47
47
|
"yaml": "^2.3.4"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Build Command
|
|
3
3
|
*
|
|
4
4
|
* Generates a static site from the Engineering Pathway data.
|
|
5
5
|
* Copies all necessary files (HTML, JS, CSS) and data to an output directory.
|
|
@@ -59,13 +59,13 @@ const PUBLIC_ASSETS = [
|
|
|
59
59
|
const ROOT_ASSETS = ["templates"];
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* Run the
|
|
62
|
+
* Run the build command
|
|
63
63
|
* @param {Object} params - Command parameters
|
|
64
64
|
* @param {string} params.dataDir - Path to data directory
|
|
65
65
|
* @param {Object} params.options - Command options
|
|
66
66
|
*/
|
|
67
|
-
export async function
|
|
68
|
-
const outputDir = options.output || join(process.cwd(), "
|
|
67
|
+
export async function runBuildCommand({ dataDir, options }) {
|
|
68
|
+
const outputDir = options.output || join(process.cwd(), "public");
|
|
69
69
|
const clean = options.clean !== false;
|
|
70
70
|
|
|
71
71
|
// Load framework config for display
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Dev Command
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Runs a live development server for the Engineering Pathway web application.
|
|
5
5
|
* Uses Node.js built-in http module (no external dependencies).
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -96,12 +96,12 @@ async function isDirectory(path) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Run the
|
|
99
|
+
* Run the dev command
|
|
100
100
|
* @param {Object} params - Command parameters
|
|
101
101
|
* @param {string} params.dataDir - Path to data directory
|
|
102
102
|
* @param {Object} params.options - Command options
|
|
103
103
|
*/
|
|
104
|
-
export async function
|
|
104
|
+
export async function runDevCommand({ dataDir, options }) {
|
|
105
105
|
const port = options.port || 3000;
|
|
106
106
|
|
|
107
107
|
// Load framework config for display
|
|
@@ -18,6 +18,13 @@ import { trimValue, trimRequired, trimFields } from "../shared.js";
|
|
|
18
18
|
* @property {string} content - Working style content (markdown)
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} BeforeHandoffEntry
|
|
23
|
+
* @property {{id: string, name: string}} skill - Skill info
|
|
24
|
+
* @property {{id: string, name: string, emojiIcon: string}} capability - Capability info
|
|
25
|
+
* @property {string[]} items - Checklist items
|
|
26
|
+
*/
|
|
27
|
+
|
|
21
28
|
/**
|
|
22
29
|
* Prepare agent profile data for template rendering
|
|
23
30
|
* Normalizes string values by trimming trailing newlines for consistent template output.
|
|
@@ -35,7 +42,7 @@ import { trimValue, trimRequired, trimFields } from "../shared.js";
|
|
|
35
42
|
* @param {Array<{name: string, dirname: string, useWhen: string}>} params.bodyData.skillIndex - Skill index entries
|
|
36
43
|
* @param {string} params.bodyData.roleContext - Role context text
|
|
37
44
|
* @param {WorkingStyleEntry[]} params.bodyData.workingStyles - Working style entries
|
|
38
|
-
* @param {
|
|
45
|
+
* @param {BeforeHandoffEntry[]} [params.bodyData.beforeHandoff] - Before handoff checklist entries
|
|
39
46
|
* @param {string[]} params.bodyData.constraints - List of constraints
|
|
40
47
|
* @param {Array<{id: string, name: string, description: string}>} [params.bodyData.agentIndex] - List of all available agents
|
|
41
48
|
* @param {boolean} [params.bodyData.hasAgentIndex] - Whether agent index is available
|
|
@@ -60,6 +67,13 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
|
|
|
60
67
|
content: "required",
|
|
61
68
|
});
|
|
62
69
|
|
|
70
|
+
// Process beforeHandoff: trim items in each entry
|
|
71
|
+
const beforeHandoff = (bodyData.beforeHandoff || []).map((entry) => ({
|
|
72
|
+
skill: entry.skill,
|
|
73
|
+
capability: entry.capability,
|
|
74
|
+
items: (entry.items || []).map((item) => trimRequired(item)),
|
|
75
|
+
}));
|
|
76
|
+
|
|
63
77
|
return {
|
|
64
78
|
// Frontmatter
|
|
65
79
|
name: frontmatter.name,
|
|
@@ -77,7 +91,8 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
|
|
|
77
91
|
roleContext: trimValue(bodyData.roleContext),
|
|
78
92
|
workingStyles,
|
|
79
93
|
hasWorkingStyles: workingStyles.length > 0,
|
|
80
|
-
beforeHandoff
|
|
94
|
+
beforeHandoff,
|
|
95
|
+
hasBeforeHandoff: beforeHandoff.length > 0,
|
|
81
96
|
constraints,
|
|
82
97
|
hasConstraints: constraints.length > 0,
|
|
83
98
|
agentIndex,
|
|
@@ -102,7 +117,7 @@ function prepareAgentProfileData({ frontmatter, bodyData }) {
|
|
|
102
117
|
* @param {Array<{name: string, dirname: string, useWhen: string}>} profile.bodyData.skillIndex - Skill index entries
|
|
103
118
|
* @param {string} profile.bodyData.roleContext - Role context text
|
|
104
119
|
* @param {WorkingStyleEntry[]} profile.bodyData.workingStyles - Working style entries
|
|
105
|
-
* @param {
|
|
120
|
+
* @param {BeforeHandoffEntry[]} [profile.bodyData.beforeHandoff] - Before handoff checklist entries (optional)
|
|
106
121
|
* @param {string[]} profile.bodyData.constraints - List of constraints
|
|
107
122
|
* @param {string} template - Mustache template string
|
|
108
123
|
* @returns {string} Complete .agent.md file content
|
|
@@ -33,7 +33,7 @@ import { createJsonLdScript, skillToJsonLd } from "../json-ld.js";
|
|
|
33
33
|
* @param {Array} context.drivers - All drivers
|
|
34
34
|
* @param {Array} context.capabilities - Capability entities
|
|
35
35
|
* @param {boolean} [context.showBackLink=true] - Whether to show back navigation link
|
|
36
|
-
* @param {boolean} [context.showToolsAndPatterns=true] - Whether to show
|
|
36
|
+
* @param {boolean} [context.showToolsAndPatterns=true] - Whether to show required tools and implementation patterns
|
|
37
37
|
* @returns {HTMLElement}
|
|
38
38
|
*/
|
|
39
39
|
export function skillToDOM(
|
|
@@ -178,11 +178,11 @@ export function skillToDOM(
|
|
|
178
178
|
)
|
|
179
179
|
: null,
|
|
180
180
|
|
|
181
|
-
//
|
|
181
|
+
// Required Tools
|
|
182
182
|
showToolsAndPatterns && view.toolReferences.length > 0
|
|
183
183
|
? div(
|
|
184
184
|
{ className: "detail-section" },
|
|
185
|
-
heading2({ className: "section-title" }, "
|
|
185
|
+
heading2({ className: "section-title" }, "Required Tools"),
|
|
186
186
|
table(
|
|
187
187
|
{ className: "tools-table" },
|
|
188
188
|
thead({}, tr({}, th({}, "Tool"), th({}, "Use When"))),
|
|
@@ -204,6 +204,7 @@ export function skillToDOM(
|
|
|
204
204
|
rel: "noopener noreferrer",
|
|
205
205
|
},
|
|
206
206
|
tool.name,
|
|
207
|
+
span({ className: "external-icon" }, " ↗"),
|
|
207
208
|
)
|
|
208
209
|
: tool.name,
|
|
209
210
|
),
|
|
@@ -105,9 +105,9 @@ export function skillToMarkdown(
|
|
|
105
105
|
lines.push("");
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
//
|
|
108
|
+
// Required tools
|
|
109
109
|
if (view.toolReferences.length > 0) {
|
|
110
|
-
lines.push("##
|
|
110
|
+
lines.push("## Required Tools", "");
|
|
111
111
|
const toolRows = view.toolReferences.map((tool) => [
|
|
112
112
|
tool.url ? `[${tool.name}](${tool.url})` : tool.name,
|
|
113
113
|
tool.useWhen,
|
|
@@ -28,12 +28,9 @@ export function createToolkitTable(toolkit) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const rows = toolkit.map((tool) => {
|
|
31
|
-
const
|
|
32
|
-
?
|
|
33
|
-
|
|
34
|
-
createToolIcon(tool.simpleIcon, tool.name),
|
|
35
|
-
)
|
|
36
|
-
: td({ className: "tool-icon-cell" });
|
|
31
|
+
const icon = tool.simpleIcon
|
|
32
|
+
? createToolIcon(tool.simpleIcon, tool.name)
|
|
33
|
+
: null;
|
|
37
34
|
|
|
38
35
|
const nameContent = tool.url
|
|
39
36
|
? a(
|
|
@@ -50,8 +47,7 @@ export function createToolkitTable(toolkit) {
|
|
|
50
47
|
|
|
51
48
|
return tr(
|
|
52
49
|
{},
|
|
53
|
-
|
|
54
|
-
td({ className: "tool-name-cell" }, nameContent),
|
|
50
|
+
td({ className: "tool-name-cell" }, icon, nameContent),
|
|
55
51
|
td({ className: "tool-description-cell" }, tool.description),
|
|
56
52
|
);
|
|
57
53
|
});
|
|
@@ -60,15 +56,7 @@ export function createToolkitTable(toolkit) {
|
|
|
60
56
|
{ className: "table-container" },
|
|
61
57
|
table(
|
|
62
58
|
{ className: "table toolkit-table" },
|
|
63
|
-
thead(
|
|
64
|
-
{},
|
|
65
|
-
tr(
|
|
66
|
-
{},
|
|
67
|
-
th({ style: "width: 40px" }, ""),
|
|
68
|
-
th({}, "Tool"),
|
|
69
|
-
th({}, "Description"),
|
|
70
|
-
),
|
|
71
|
-
),
|
|
59
|
+
thead({}, tr({}, th({}, "Tool"), th({}, "Description"))),
|
|
72
60
|
tbody({}, ...rows),
|
|
73
61
|
),
|
|
74
62
|
);
|
package/src/lib/card-mappers.js
CHANGED
|
@@ -190,7 +190,7 @@ export function toolToCardConfig(tool, capabilities) {
|
|
|
190
190
|
title: tool.name,
|
|
191
191
|
description: tool.description,
|
|
192
192
|
// Docs link in header badges (upper right)
|
|
193
|
-
badges: tool.url ? [createExternalLink("Docs
|
|
193
|
+
badges: tool.url ? [createExternalLink("Docs ↗", tool.url)] : [],
|
|
194
194
|
content: skillsList,
|
|
195
195
|
icon,
|
|
196
196
|
};
|
|
@@ -50,17 +50,18 @@ handoffs:
|
|
|
50
50
|
{{/hasWorkingStyles}}
|
|
51
51
|
{{#hasSkills}}
|
|
52
52
|
|
|
53
|
-
##
|
|
53
|
+
## Required Skills
|
|
54
54
|
|
|
55
|
-
**
|
|
56
|
-
project-specific guidance, tools and technology
|
|
57
|
-
|
|
55
|
+
**MANDATORY:** Before starting work, you MUST read the relevant skill files for
|
|
56
|
+
project-specific guidance, required tools, and technology standards. Pre-training
|
|
57
|
+
knowledge alone is insufficient—skills contain organizational standards that
|
|
58
|
+
override general knowledge.
|
|
58
59
|
|
|
59
|
-
Skills represent
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
Skills represent mandatory organizational patterns. When a skill specifies tools
|
|
61
|
+
in its "Required Tools" section, you MUST use them. If a blocking constraint
|
|
62
|
+
prevents use, document in your output: (1) which skill requirement you cannot
|
|
63
|
+
meet, (2) the specific constraint preventing compliance, and (3) the alternative
|
|
64
|
+
approach with acknowledged trade-offs.
|
|
64
65
|
|
|
65
66
|
| Skill | Location | Use When |
|
|
66
67
|
| ----- | -------- | -------- |
|
|
@@ -70,16 +71,16 @@ and (3) trade-offs of the alternative.
|
|
|
70
71
|
{{/hasSkills}}
|
|
71
72
|
{{#hasAgentIndex}}
|
|
72
73
|
|
|
73
|
-
##
|
|
74
|
+
## Required Sub-Agent Delegations
|
|
74
75
|
|
|
75
|
-
**
|
|
76
|
-
|
|
76
|
+
**MANDATORY:** You MUST delegate work outside your speciality using the
|
|
77
|
+
`runSubagent` tool. Do not attempt work that another agent is better suited for.
|
|
77
78
|
|
|
78
|
-
You are part of
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
You are part of an agentic team with specialized roles. Attempting work outside
|
|
80
|
+
your speciality produces inferior results and violates team structure. If you
|
|
81
|
+
cannot delegate due to a blocking constraint, document in your output: (1) the
|
|
82
|
+
specialized work required, (2) the specific constraint preventing delegation,
|
|
83
|
+
and (3) the compromised approach with acknowledged limitations.
|
|
83
84
|
|
|
84
85
|
| Agent Name | Speciality | Description |
|
|
85
86
|
| ---------- | ---------- | ----------- |
|
|
@@ -87,17 +88,23 @@ preventing delegation and (3) trade-offs of the alternative.
|
|
|
87
88
|
| `{{id}}` | {{{name}}} | {{{description}}} |
|
|
88
89
|
{{/agentIndex}}
|
|
89
90
|
{{/hasAgentIndex}}
|
|
90
|
-
{{#
|
|
91
|
+
{{#hasBeforeHandoff}}
|
|
91
92
|
|
|
92
93
|
## Before Handoff
|
|
93
94
|
|
|
94
95
|
Before offering a handoff, verify and summarize completion of these items:
|
|
95
96
|
|
|
96
|
-
{{
|
|
97
|
+
{{#beforeHandoff}}
|
|
98
|
+
### {{{capability.emojiIcon}}} {{{skill.name}}}
|
|
99
|
+
|
|
100
|
+
{{#items}}
|
|
101
|
+
- [ ] {{{.}}}
|
|
102
|
+
{{/items}}
|
|
97
103
|
|
|
104
|
+
{{/beforeHandoff}}
|
|
98
105
|
When verified, summarize what was accomplished then offer the handoff. If items
|
|
99
106
|
are incomplete, explain what remains.
|
|
100
|
-
{{/
|
|
107
|
+
{{/hasBeforeHandoff}}
|
|
101
108
|
|
|
102
109
|
## Return Format
|
|
103
110
|
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: {{name}}
|
|
3
3
|
description: |
|
|
4
|
-
{{#descriptionLines}}
|
|
5
|
-
{{{.}}}
|
|
6
|
-
{{/descriptionLines}}
|
|
4
|
+
{{#descriptionLines}}{{{.}}} {{/descriptionLines}}
|
|
7
5
|
{{#hasUseWhen}}
|
|
8
|
-
|
|
6
|
+
Use When: {{#useWhenLines}}{{{.}}} {{/useWhenLines}}
|
|
9
7
|
{{/hasUseWhen}}
|
|
10
8
|
---
|
|
11
9
|
|
|
12
10
|
# {{{title}}}
|
|
13
|
-
{{#hasUseWhen}}
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
{{
|
|
17
|
-
{{/
|
|
12
|
+
{{#descriptionLines}}
|
|
13
|
+
{{{.}}}
|
|
14
|
+
{{/descriptionLines}}
|
|
18
15
|
{{#hasStages}}
|
|
19
16
|
|
|
20
17
|
## Stage Guidance
|
|
@@ -37,7 +34,10 @@ description: |
|
|
|
37
34
|
{{/hasStages}}
|
|
38
35
|
{{#hasToolReferences}}
|
|
39
36
|
|
|
40
|
-
#
|
|
37
|
+
# Required Tools
|
|
38
|
+
|
|
39
|
+
Use these tools when applying this skill. Alternative tools require documented
|
|
40
|
+
justification with acknowledged trade-offs.
|
|
41
41
|
|
|
42
42
|
| Tool | Use When |
|
|
43
43
|
| ---- | -------- |
|