@forwardimpact/pathway 0.13.0 → 0.14.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 (45) hide show
  1. package/bin/fit-pathway.js +26 -7
  2. package/package.json +2 -2
  3. package/src/commands/build.js +98 -2
  4. package/src/commands/index.js +1 -0
  5. package/src/commands/job.js +1 -0
  6. package/src/commands/stage.js +8 -8
  7. package/src/commands/update.js +133 -0
  8. package/src/components/command-prompt.js +85 -0
  9. package/src/components/nav.js +2 -2
  10. package/src/components/top-bar.js +97 -0
  11. package/src/css/bundles/app.css +2 -0
  12. package/src/css/components/command-prompt.css +98 -0
  13. package/src/css/components/layout.css +0 -3
  14. package/src/css/components/nav.css +121 -81
  15. package/src/css/components/surfaces.css +1 -1
  16. package/src/css/components/top-bar.css +180 -0
  17. package/src/css/pages/agent-builder.css +0 -9
  18. package/src/css/pages/landing.css +4 -0
  19. package/src/css/pages/lifecycle.css +5 -2
  20. package/src/css/reset.css +1 -1
  21. package/src/css/tokens.css +4 -2
  22. package/src/css/views/slide-base.css +2 -1
  23. package/src/formatters/agent/dom.js +0 -26
  24. package/src/formatters/agent/profile.js +13 -7
  25. package/src/formatters/agent/skill.js +4 -4
  26. package/src/formatters/stage/dom.js +13 -10
  27. package/src/formatters/stage/microdata.js +14 -8
  28. package/src/formatters/stage/shared.js +4 -4
  29. package/src/index.html +69 -44
  30. package/src/lib/cli-command.js +145 -0
  31. package/src/lib/state.js +2 -0
  32. package/src/main.js +47 -26
  33. package/src/pages/agent-builder.js +0 -28
  34. package/src/pages/behaviour.js +3 -1
  35. package/src/pages/discipline.js +3 -1
  36. package/src/pages/driver.js +6 -1
  37. package/src/pages/grade.js +6 -1
  38. package/src/pages/job.js +1 -0
  39. package/src/pages/landing.js +7 -0
  40. package/src/pages/skill.js +9 -2
  41. package/src/pages/track.js +6 -1
  42. package/src/slides/job.js +1 -0
  43. package/templates/agent.template.md +17 -10
  44. package/templates/install.template.sh +33 -0
  45. package/templates/skill.template.md +15 -7
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Command Prompt
3
+ *
4
+ * Terminal-style command display with copy button.
5
+ * Pill-shaped container with $ prompt, monospace text, and copy action.
6
+ */
7
+
8
+ @layer components {
9
+ .command-prompt {
10
+ width: 100%;
11
+ max-width: 600px;
12
+ margin: 0 auto;
13
+ display: flex;
14
+ align-items: center;
15
+ height: 36px;
16
+ padding: 0 var(--space-sm) 0 var(--space-md);
17
+ border: 1px solid var(--color-border);
18
+ border-radius: var(--radius-lg);
19
+ background: var(--color-surface);
20
+ gap: var(--space-xs);
21
+ transition:
22
+ border-color 0.15s,
23
+ box-shadow 0.15s;
24
+ }
25
+
26
+ .command-prompt:hover {
27
+ border-color: var(--color-text-light);
28
+ }
29
+
30
+ /* Terminal prompt symbol */
31
+ .command-prompt__prompt {
32
+ flex-shrink: 0;
33
+ font-size: var(--font-size-sm);
34
+ color: var(--color-text-light);
35
+ user-select: none;
36
+ }
37
+
38
+ /* Command text */
39
+ .command-prompt__text {
40
+ flex: 1;
41
+ min-width: 0;
42
+ font-family: var(--font-family-mono);
43
+ font-size: var(--font-size-xs);
44
+ color: var(--color-text-secondary);
45
+ white-space: nowrap;
46
+ overflow: hidden;
47
+ text-overflow: ellipsis;
48
+ user-select: all;
49
+ line-height: 36px;
50
+ }
51
+
52
+ /* Copy button */
53
+ .command-prompt__copy {
54
+ flex-shrink: 0;
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ width: 28px;
59
+ height: 28px;
60
+ border: none;
61
+ border-radius: var(--radius-sm);
62
+ background: transparent;
63
+ color: var(--color-text-light);
64
+ cursor: pointer;
65
+ transition:
66
+ background 0.15s,
67
+ color 0.15s;
68
+ }
69
+
70
+ .command-prompt__copy:hover {
71
+ background: var(--color-border);
72
+ color: var(--color-text);
73
+ }
74
+
75
+ .command-prompt__copy svg {
76
+ width: 14px;
77
+ height: 14px;
78
+ fill: none;
79
+ stroke: currentColor;
80
+ stroke-width: 2;
81
+ stroke-linecap: round;
82
+ stroke-linejoin: round;
83
+ }
84
+
85
+ /* Copied state */
86
+ .command-prompt__copy.copied {
87
+ color: var(--color-success);
88
+ }
89
+
90
+ /* --------------------------------------------------------------------------
91
+ Mobile tweaks
92
+ -------------------------------------------------------------------------- */
93
+ @media (max-width: 768px) {
94
+ .command-prompt__prompt {
95
+ display: none;
96
+ }
97
+ }
98
+ }
@@ -8,8 +8,6 @@
8
8
  /* App container */
9
9
  #app {
10
10
  min-height: 100vh;
11
- display: flex;
12
- flex-direction: column;
13
11
  }
14
12
 
15
13
  #app-content {
@@ -18,7 +16,6 @@
18
16
  width: 100%;
19
17
  margin: 0 auto;
20
18
  padding: var(--space-lg);
21
- padding-top: calc(var(--nav-height) + var(--space-lg));
22
19
  }
23
20
 
24
21
  /* Stack - vertical flex container with gap */
@@ -1,44 +1,73 @@
1
1
  /**
2
- * Navigation Component
2
+ * Navigation Drawer
3
3
  *
4
- * Fixed navigation bar, brand, links, and mobile hamburger menu.
4
+ * Left-hand drawer with vertically stacked links, toggled by top bar button.
5
+ * Open by default on desktop, overlays on mobile.
5
6
  */
6
7
 
7
8
  @layer components {
8
- #app-nav {
9
+ /* --------------------------------------------------------------------------
10
+ Drawer Panel
11
+ -------------------------------------------------------------------------- */
12
+ #app-drawer {
9
13
  position: fixed;
10
- top: 0;
14
+ top: var(--top-bar-height);
11
15
  left: 0;
12
- right: 0;
13
- height: var(--nav-height);
16
+ bottom: 0;
17
+ width: var(--drawer-width);
14
18
  background: var(--color-surface);
15
- border-bottom: 1px solid var(--color-border);
16
- display: flex;
17
- align-items: center;
18
- padding: 0 var(--space-lg);
19
+ border-right: 1px solid var(--color-border);
19
20
  z-index: 100;
20
- box-shadow: var(--shadow-sm);
21
+ overflow-y: auto;
22
+ display: flex;
23
+ flex-direction: column;
24
+ transform: translateX(calc(-1 * var(--drawer-width)));
25
+ transition: transform 0.3s ease;
26
+ }
27
+
28
+ .drawer-open #app-drawer {
29
+ transform: translateX(0);
30
+ }
31
+
32
+ /* --------------------------------------------------------------------------
33
+ Drawer Header - brand area
34
+ -------------------------------------------------------------------------- */
35
+ .drawer-header {
36
+ padding: var(--space-lg) var(--space-md);
37
+ border-bottom: 1px solid var(--color-border);
38
+ flex-shrink: 0;
21
39
  }
22
40
 
23
41
  .nav-brand {
24
42
  display: flex;
43
+ flex-direction: column;
25
44
  align-items: center;
26
- gap: var(--space-sm);
45
+ gap: var(--space-xs);
46
+ text-decoration: none;
47
+ color: var(--color-text);
48
+ }
49
+
50
+ .brand-emoji {
51
+ font-size: 2.5rem;
52
+ line-height: 1;
27
53
  }
28
54
 
29
- .nav-brand a {
55
+ .nav-brand:hover {
56
+ text-decoration: none;
57
+ }
58
+
59
+ .brand-title {
30
60
  font-size: var(--font-size-lg);
31
61
  font-weight: 700;
32
62
  color: var(--color-text);
33
- text-decoration: none;
34
63
  }
35
64
 
36
- .nav-brand a:hover {
65
+ .nav-brand:hover .brand-title {
37
66
  color: var(--color-primary);
38
- text-decoration: none;
39
67
  }
40
68
 
41
69
  .brand-tag {
70
+ display: inline-block;
42
71
  font-size: var(--font-size-xs);
43
72
  font-weight: 600;
44
73
  letter-spacing: 0.5px;
@@ -70,97 +99,108 @@
70
99
  }
71
100
  }
72
101
 
73
- .nav-links {
102
+ /* --------------------------------------------------------------------------
103
+ Drawer Navigation - sections and links
104
+ -------------------------------------------------------------------------- */
105
+ .drawer-nav {
106
+ flex: 1;
107
+ overflow-y: auto;
108
+ padding: var(--space-sm) 0;
109
+ }
110
+
111
+ .drawer-section {
74
112
  display: flex;
75
- gap: var(--space-xs);
76
- margin-left: auto;
77
- align-items: center;
113
+ flex-direction: column;
114
+ padding: var(--space-sm) 0;
78
115
  }
79
116
 
80
- .nav-links a {
117
+ .drawer-section + .drawer-section {
118
+ border-top: 1px solid var(--color-border);
119
+ }
120
+
121
+ .drawer-section-label {
122
+ font-size: var(--font-size-xs);
123
+ font-weight: 600;
124
+ text-transform: uppercase;
125
+ letter-spacing: 0.05em;
126
+ color: var(--color-text-light);
127
+ padding: var(--space-xs) var(--space-md);
128
+ margin-bottom: var(--space-xs);
129
+ }
130
+
131
+ .drawer-nav a {
132
+ display: block;
81
133
  color: var(--color-text-muted);
82
134
  font-weight: 500;
83
- font-size: 0.9rem;
84
- padding: var(--space-xs) var(--space-sm);
85
- border-radius: var(--radius-md);
86
- transition: all 0.2s;
87
- white-space: nowrap;
135
+ font-size: var(--font-size-sm);
136
+ padding: var(--space-xs) var(--space-md);
137
+ text-decoration: none;
138
+ transition: all 0.15s;
139
+ border-left: 3px solid transparent;
88
140
  }
89
141
 
90
- .nav-links a:hover {
142
+ .drawer-nav a:hover {
91
143
  color: var(--color-primary);
92
- background: var(--color-primary-light);
93
- background: rgba(59, 130, 246, 0.1);
144
+ background: rgba(59, 130, 246, 0.06);
145
+ border-left-color: var(--color-primary-light);
94
146
  text-decoration: none;
95
147
  }
96
148
 
97
- .nav-cta {
98
- background: var(--color-primary) !important;
99
- color: white !important;
149
+ .drawer-nav a.active {
150
+ color: var(--color-primary);
151
+ background: rgba(59, 130, 246, 0.1);
152
+ border-left-color: var(--color-primary);
153
+ font-weight: 600;
100
154
  }
101
155
 
102
- .nav-cta:hover {
103
- background: var(--color-primary-dark) !important;
104
- color: white !important;
156
+ /* CTA links in drawer */
157
+ .drawer-cta {
158
+ color: var(--color-primary) !important;
159
+ font-weight: 600 !important;
105
160
  }
106
161
 
107
- .nav-toggle {
108
- display: none;
109
- flex-direction: column;
110
- gap: 4px;
111
- background: none;
112
- border: none;
113
- cursor: pointer;
114
- padding: var(--space-sm);
115
- margin-left: auto;
162
+ .drawer-cta:hover {
163
+ background: rgba(59, 130, 246, 0.1) !important;
116
164
  }
117
165
 
118
- .nav-toggle span {
119
- display: block;
120
- width: 24px;
121
- height: 2px;
122
- background: var(--color-text);
123
- transition: all 0.3s;
124
- }
125
-
126
- .nav-toggle-active span:nth-child(1) {
127
- transform: rotate(45deg) translate(4px, 4px);
166
+ /* --------------------------------------------------------------------------
167
+ App Body - content area that shifts with drawer
168
+ -------------------------------------------------------------------------- */
169
+ .app-body {
170
+ min-height: 100vh;
171
+ display: flex;
172
+ flex-direction: column;
173
+ transition: margin-left 0.3s ease;
128
174
  }
129
175
 
130
- .nav-toggle-active span:nth-child(2) {
131
- opacity: 0;
176
+ .drawer-open .app-body {
177
+ margin-left: var(--drawer-width);
132
178
  }
133
179
 
134
- .nav-toggle-active span:nth-child(3) {
135
- transform: rotate(-45deg) translate(4px, -4px);
180
+ /* --------------------------------------------------------------------------
181
+ Drawer Overlay - backdrop on mobile when drawer is open
182
+ -------------------------------------------------------------------------- */
183
+ .drawer-overlay {
184
+ display: none;
185
+ position: fixed;
186
+ top: var(--top-bar-height);
187
+ left: 0;
188
+ right: 0;
189
+ bottom: 0;
190
+ background: rgba(0, 0, 0, 0.3);
191
+ z-index: 90;
136
192
  }
137
193
 
138
- /* Mobile navigation */
139
- @media (max-width: 1280px) {
140
- .nav-toggle {
141
- display: flex;
142
- }
143
-
144
- .nav-links {
145
- position: absolute;
146
- top: var(--nav-height);
147
- left: 0;
148
- right: 0;
149
- flex-direction: column;
150
- background: var(--color-surface);
151
- border-bottom: 1px solid var(--color-border);
152
- padding: var(--space-md);
153
- display: none;
154
- gap: var(--space-xs);
155
- }
156
-
157
- .nav-links.nav-open {
158
- display: flex;
194
+ /* --------------------------------------------------------------------------
195
+ Mobile - overlay instead of push
196
+ -------------------------------------------------------------------------- */
197
+ @media (max-width: 768px) {
198
+ .drawer-open .app-body {
199
+ margin-left: 0;
159
200
  }
160
201
 
161
- .nav-links a {
202
+ .drawer-open .drawer-overlay {
162
203
  display: block;
163
- text-align: center;
164
204
  }
165
205
  }
166
206
  }
@@ -168,7 +168,7 @@
168
168
  .page-title {
169
169
  font-size: var(--font-size-3xl);
170
170
  font-weight: 700;
171
- margin: 0 0 var(--space-sm);
171
+ margin: 0 0 var(--space-md);
172
172
  }
173
173
 
174
174
  .page-description {
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Top Bar
3
+ *
4
+ * Fixed bar across the top of the viewport with sidebar toggle and
5
+ * CLI command display. Inspired by Safari's URL bar + sidebar layout.
6
+ */
7
+
8
+ @layer components {
9
+ /* --------------------------------------------------------------------------
10
+ Bar container - fixed across top
11
+ -------------------------------------------------------------------------- */
12
+ .top-bar {
13
+ position: fixed;
14
+ top: 0;
15
+ left: 0;
16
+ right: 0;
17
+ height: var(--top-bar-height);
18
+ z-index: 200;
19
+ display: flex;
20
+ align-items: center;
21
+ gap: var(--space-sm);
22
+ padding: 0 var(--space-sm);
23
+ background: var(--color-surface);
24
+ border-bottom: 1px solid var(--color-border);
25
+ }
26
+
27
+ /* --------------------------------------------------------------------------
28
+ Sidebar toggle button
29
+ -------------------------------------------------------------------------- */
30
+ .top-bar__toggle {
31
+ flex-shrink: 0;
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ width: 36px;
36
+ height: 36px;
37
+ border: none;
38
+ border-radius: var(--radius-md);
39
+ background: transparent;
40
+ color: var(--color-text-muted);
41
+ cursor: pointer;
42
+ transition:
43
+ background 0.15s,
44
+ color 0.15s;
45
+ }
46
+
47
+ .top-bar__toggle:hover {
48
+ background: var(--color-bg-secondary);
49
+ color: var(--color-text);
50
+ }
51
+
52
+ .top-bar__toggle:active {
53
+ background: var(--color-border);
54
+ }
55
+
56
+ /* Sidebar icon: simple sidebar SVG */
57
+ .top-bar__toggle svg {
58
+ width: 18px;
59
+ height: 18px;
60
+ fill: none;
61
+ stroke: currentColor;
62
+ stroke-width: 1.5;
63
+ stroke-linecap: round;
64
+ stroke-linejoin: round;
65
+ }
66
+
67
+ /* Highlight toggle when drawer is open */
68
+ .drawer-open .top-bar__toggle {
69
+ color: var(--color-primary);
70
+ background: rgba(59, 130, 246, 0.08);
71
+ }
72
+
73
+ /* --------------------------------------------------------------------------
74
+ Command bar (mimics Safari-style URL bar)
75
+ -------------------------------------------------------------------------- */
76
+ .top-bar__command {
77
+ width: 100%;
78
+ max-width: 800px;
79
+ margin: 0 auto;
80
+ display: flex;
81
+ align-items: center;
82
+ height: 36px;
83
+ padding: 0 var(--space-sm) 0 var(--space-md);
84
+ border: 1px solid var(--color-border);
85
+ border-radius: var(--radius-lg);
86
+ transition:
87
+ border-color 0.15s,
88
+ box-shadow 0.15s;
89
+ gap: var(--space-xs);
90
+ }
91
+
92
+ .top-bar__command:hover {
93
+ border-color: var(--color-text-light);
94
+ }
95
+
96
+ .top-bar__command:focus-within {
97
+ border-color: var(--color-primary);
98
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
99
+ }
100
+
101
+ /* Terminal prompt icon */
102
+ .top-bar__prompt {
103
+ flex-shrink: 0;
104
+ font-size: var(--font-size-sm);
105
+ color: var(--color-text-light);
106
+ user-select: none;
107
+ }
108
+
109
+ /* CLI command text */
110
+ .top-bar__command-text {
111
+ flex: 1;
112
+ min-width: 0;
113
+ font-family: var(--font-family-mono);
114
+ font-size: var(--font-size-xs);
115
+ color: var(--color-text-secondary);
116
+ white-space: nowrap;
117
+ overflow: hidden;
118
+ text-overflow: ellipsis;
119
+ user-select: all;
120
+ line-height: 36px;
121
+ }
122
+
123
+ /* Copy button inside the command bar */
124
+ .top-bar__copy {
125
+ flex-shrink: 0;
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ width: 28px;
130
+ height: 28px;
131
+ border: none;
132
+ border-radius: var(--radius-sm);
133
+ background: transparent;
134
+ color: var(--color-text-light);
135
+ cursor: pointer;
136
+ transition:
137
+ background 0.15s,
138
+ color 0.15s;
139
+ }
140
+
141
+ .top-bar__copy:hover {
142
+ background: var(--color-border);
143
+ color: var(--color-text);
144
+ }
145
+
146
+ .top-bar__copy svg {
147
+ width: 14px;
148
+ height: 14px;
149
+ fill: none;
150
+ stroke: currentColor;
151
+ stroke-width: 2;
152
+ stroke-linecap: round;
153
+ stroke-linejoin: round;
154
+ }
155
+
156
+ /* Copied state */
157
+ .top-bar__copy.copied {
158
+ color: var(--color-success);
159
+ }
160
+
161
+ .top-bar__copy.copied svg {
162
+ /* Swap from copy icon to checkmark via CSS — JS swaps the class */
163
+ }
164
+
165
+ /* --------------------------------------------------------------------------
166
+ Layout adjustments - push content below the top bar
167
+ -------------------------------------------------------------------------- */
168
+ .app-body {
169
+ padding-top: var(--top-bar-height);
170
+ }
171
+
172
+ /* --------------------------------------------------------------------------
173
+ Mobile tweaks
174
+ -------------------------------------------------------------------------- */
175
+ @media (max-width: 768px) {
176
+ .top-bar__prompt {
177
+ display: none;
178
+ }
179
+ }
180
+ }
@@ -160,15 +160,6 @@
160
160
  gap: var(--space-md);
161
161
  }
162
162
 
163
- /* CLI hint */
164
- .cli-hint {
165
- background: var(--color-bg);
166
- }
167
-
168
- .cli-hint h2 {
169
- margin-bottom: var(--space-sm);
170
- }
171
-
172
163
  /* Role agents list */
173
164
  .role-agents-list {
174
165
  display: flex;
@@ -37,6 +37,10 @@
37
37
  margin: 0 auto var(--space-xl);
38
38
  }
39
39
 
40
+ .landing-hero .command-prompt {
41
+ margin-bottom: var(--space-xl);
42
+ }
43
+
40
44
  @media (max-width: 640px) {
41
45
  .landing-hero h1 {
42
46
  font-size: var(--font-size-2xl);
@@ -21,9 +21,11 @@
21
21
  display: flex;
22
22
  align-items: center;
23
23
  gap: var(--space-md);
24
+ flex: 1;
24
25
  }
25
26
 
26
27
  .lifecycle-stage {
28
+ flex: 1;
27
29
  display: flex;
28
30
  flex-direction: column;
29
31
  align-items: center;
@@ -67,8 +69,9 @@
67
69
  flex-wrap: wrap;
68
70
  }
69
71
 
70
- .page-title-row .page-title {
71
- margin: 0;
72
+ .page-title-row .page-title,
73
+ .page-title-row .page-title-badges {
74
+ margin: 0 0 var(--space-md);
72
75
  }
73
76
 
74
77
  /* Criteria and constraints */
package/src/css/reset.css CHANGED
@@ -28,7 +28,7 @@
28
28
  h5,
29
29
  h6 {
30
30
  margin: 0;
31
- line-height: 1.3;
31
+ line-height: 1;
32
32
  font-weight: 600;
33
33
  }
34
34
 
@@ -149,11 +149,13 @@
149
149
  Layout
150
150
  -------------------------------------------------------------------------- */
151
151
  --max-width: 1400px;
152
- --nav-height: 60px;
152
+ --drawer-width: 240px;
153
+ --top-bar-height: 48px;
153
154
 
154
155
  /*
155
156
  * Responsive breakpoints (used in @media queries):
156
- * - 1280px: Tablet/laptop - nav hamburger, layout stacking
157
+ * - 1280px: Tablet/laptop - layout stacking
158
+ * - 768px: Mobile - drawer overlays instead of pushing content
157
159
  * - 640px: Mobile - full-width buttons, simplified layouts
158
160
  */
159
161
  }
@@ -241,7 +241,8 @@
241
241
  .slide-view footer,
242
242
  .slide-view .action-buttons,
243
243
  .slide-view .back-link,
244
- .slide-view #app-nav,
244
+ .slide-view #app-drawer,
245
+ .slide-view .top-bar,
245
246
  .slide-view #app-footer {
246
247
  display: none !important;
247
248
  }
@@ -92,14 +92,6 @@ export function agentDeploymentToDOM({
92
92
  "No skills with agent sections found for this discipline.",
93
93
  ),
94
94
  ),
95
-
96
- // CLI hint section
97
- section(
98
- { className: "agent-section cli-hint" },
99
- h2({}, "CLI Alternative"),
100
- p({}, "Generate this agent from the command line:"),
101
- createCliCommand(agentName),
102
- ),
103
95
  );
104
96
  }
105
97
 
@@ -200,24 +192,6 @@ function createRoleAgentCard(agent) {
200
192
  );
201
193
  }
202
194
 
203
- /**
204
- * Create CLI command display
205
- * @param {string} agentName - Agent name (kebab-case)
206
- * @returns {HTMLElement}
207
- */
208
- function createCliCommand(agentName) {
209
- // Convert kebab-case name to discipline and track
210
- const parts = agentName.split("-");
211
- const track = parts.pop();
212
- const discipline = parts.join("_");
213
-
214
- const command = `npx pathway agent ${discipline} ${track} --output=.github --all-roles`;
215
-
216
- return createCodeDisplay({
217
- content: command,
218
- language: "bash",
219
- });
220
- }
221
195
 
222
196
  /**
223
197
  * Download all agent files as a ZIP