@forwardimpact/pathway 0.1.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/LICENSE +201 -0
- package/README.md +104 -0
- package/app/commands/agent.js +430 -0
- package/app/commands/behaviour.js +61 -0
- package/app/commands/command-factory.js +211 -0
- package/app/commands/discipline.js +58 -0
- package/app/commands/driver.js +94 -0
- package/app/commands/grade.js +60 -0
- package/app/commands/index.js +20 -0
- package/app/commands/init.js +67 -0
- package/app/commands/interview.js +68 -0
- package/app/commands/job.js +157 -0
- package/app/commands/progress.js +77 -0
- package/app/commands/questions.js +179 -0
- package/app/commands/serve.js +143 -0
- package/app/commands/site.js +121 -0
- package/app/commands/skill.js +76 -0
- package/app/commands/stage.js +129 -0
- package/app/commands/track.js +70 -0
- package/app/components/action-buttons.js +66 -0
- package/app/components/behaviour-profile.js +53 -0
- package/app/components/builder.js +341 -0
- package/app/components/card.js +98 -0
- package/app/components/checklist.js +145 -0
- package/app/components/comparison-radar.js +237 -0
- package/app/components/detail.js +230 -0
- package/app/components/error-page.js +72 -0
- package/app/components/grid.js +109 -0
- package/app/components/list.js +120 -0
- package/app/components/modifier-table.js +142 -0
- package/app/components/nav.js +64 -0
- package/app/components/progression-table.js +320 -0
- package/app/components/radar-chart.js +102 -0
- package/app/components/skill-matrix.js +97 -0
- package/app/css/base.css +56 -0
- package/app/css/bundles/app.css +40 -0
- package/app/css/bundles/handout.css +43 -0
- package/app/css/bundles/slides.css +40 -0
- package/app/css/components/badges.css +215 -0
- package/app/css/components/buttons.css +101 -0
- package/app/css/components/forms.css +105 -0
- package/app/css/components/layout.css +209 -0
- package/app/css/components/nav.css +166 -0
- package/app/css/components/progress.css +166 -0
- package/app/css/components/states.css +82 -0
- package/app/css/components/surfaces.css +243 -0
- package/app/css/components/tables.css +362 -0
- package/app/css/components/typography.css +122 -0
- package/app/css/components/utilities.css +41 -0
- package/app/css/pages/agent-builder.css +391 -0
- package/app/css/pages/assessment-results.css +453 -0
- package/app/css/pages/detail.css +59 -0
- package/app/css/pages/interview-builder.css +148 -0
- package/app/css/pages/job-builder.css +134 -0
- package/app/css/pages/landing.css +92 -0
- package/app/css/pages/lifecycle.css +118 -0
- package/app/css/pages/progress-builder.css +274 -0
- package/app/css/pages/self-assessment.css +502 -0
- package/app/css/reset.css +50 -0
- package/app/css/tokens.css +153 -0
- package/app/css/views/handout.css +30 -0
- package/app/css/views/print.css +608 -0
- package/app/css/views/slide-animations.css +113 -0
- package/app/css/views/slide-base.css +330 -0
- package/app/css/views/slide-sections.css +597 -0
- package/app/css/views/slide-tables.css +275 -0
- package/app/formatters/agent/dom.js +540 -0
- package/app/formatters/agent/profile.js +133 -0
- package/app/formatters/agent/skill.js +58 -0
- package/app/formatters/behaviour/dom.js +91 -0
- package/app/formatters/behaviour/markdown.js +54 -0
- package/app/formatters/behaviour/shared.js +64 -0
- package/app/formatters/discipline/dom.js +187 -0
- package/app/formatters/discipline/markdown.js +87 -0
- package/app/formatters/discipline/shared.js +131 -0
- package/app/formatters/driver/dom.js +103 -0
- package/app/formatters/driver/shared.js +92 -0
- package/app/formatters/grade/dom.js +208 -0
- package/app/formatters/grade/markdown.js +94 -0
- package/app/formatters/grade/shared.js +86 -0
- package/app/formatters/index.js +50 -0
- package/app/formatters/interview/dom.js +97 -0
- package/app/formatters/interview/markdown.js +66 -0
- package/app/formatters/interview/shared.js +332 -0
- package/app/formatters/job/description.js +176 -0
- package/app/formatters/job/dom.js +411 -0
- package/app/formatters/job/markdown.js +102 -0
- package/app/formatters/progress/dom.js +135 -0
- package/app/formatters/progress/markdown.js +86 -0
- package/app/formatters/progress/shared.js +339 -0
- package/app/formatters/questions/json.js +43 -0
- package/app/formatters/questions/markdown.js +303 -0
- package/app/formatters/questions/shared.js +274 -0
- package/app/formatters/questions/yaml.js +76 -0
- package/app/formatters/shared.js +71 -0
- package/app/formatters/skill/dom.js +168 -0
- package/app/formatters/skill/markdown.js +109 -0
- package/app/formatters/skill/shared.js +125 -0
- package/app/formatters/stage/dom.js +135 -0
- package/app/formatters/stage/index.js +12 -0
- package/app/formatters/stage/shared.js +111 -0
- package/app/formatters/track/dom.js +128 -0
- package/app/formatters/track/markdown.js +105 -0
- package/app/formatters/track/shared.js +181 -0
- package/app/handout-main.js +421 -0
- package/app/handout.html +21 -0
- package/app/index.html +59 -0
- package/app/lib/card-mappers.js +173 -0
- package/app/lib/cli-output.js +270 -0
- package/app/lib/error-boundary.js +70 -0
- package/app/lib/errors.js +49 -0
- package/app/lib/form-controls.js +47 -0
- package/app/lib/job-cache.js +86 -0
- package/app/lib/markdown.js +114 -0
- package/app/lib/radar.js +866 -0
- package/app/lib/reactive.js +77 -0
- package/app/lib/render.js +212 -0
- package/app/lib/router-core.js +160 -0
- package/app/lib/router-pages.js +16 -0
- package/app/lib/router-slides.js +202 -0
- package/app/lib/state.js +148 -0
- package/app/lib/utils.js +14 -0
- package/app/lib/yaml-loader.js +327 -0
- package/app/main.js +213 -0
- package/app/model/agent.js +702 -0
- package/app/model/checklist.js +137 -0
- package/app/model/derivation.js +699 -0
- package/app/model/index-generator.js +71 -0
- package/app/model/interview.js +539 -0
- package/app/model/job.js +222 -0
- package/app/model/levels.js +591 -0
- package/app/model/loader.js +564 -0
- package/app/model/matching.js +858 -0
- package/app/model/modifiers.js +158 -0
- package/app/model/profile.js +266 -0
- package/app/model/progression.js +507 -0
- package/app/model/validation.js +1385 -0
- package/app/pages/agent-builder.js +823 -0
- package/app/pages/assessment-results.js +507 -0
- package/app/pages/behaviour.js +70 -0
- package/app/pages/discipline.js +71 -0
- package/app/pages/driver.js +106 -0
- package/app/pages/grade.js +117 -0
- package/app/pages/interview-builder.js +50 -0
- package/app/pages/interview.js +304 -0
- package/app/pages/job-builder.js +50 -0
- package/app/pages/job.js +58 -0
- package/app/pages/landing.js +305 -0
- package/app/pages/progress-builder.js +58 -0
- package/app/pages/progress.js +495 -0
- package/app/pages/self-assessment.js +729 -0
- package/app/pages/skill.js +113 -0
- package/app/pages/stage.js +231 -0
- package/app/pages/track.js +69 -0
- package/app/slide-main.js +360 -0
- package/app/slides/behaviour.js +38 -0
- package/app/slides/chapter.js +82 -0
- package/app/slides/discipline.js +40 -0
- package/app/slides/driver.js +39 -0
- package/app/slides/grade.js +32 -0
- package/app/slides/index.js +198 -0
- package/app/slides/interview.js +58 -0
- package/app/slides/job.js +55 -0
- package/app/slides/overview.js +126 -0
- package/app/slides/progress.js +83 -0
- package/app/slides/skill.js +40 -0
- package/app/slides/track.js +39 -0
- package/app/slides.html +56 -0
- package/app/types.js +147 -0
- package/bin/pathway.js +489 -0
- package/examples/agents/.claude/skills/architecture-design/SKILL.md +88 -0
- package/examples/agents/.claude/skills/cloud-platforms/SKILL.md +90 -0
- package/examples/agents/.claude/skills/code-quality-review/SKILL.md +67 -0
- package/examples/agents/.claude/skills/data-modeling/SKILL.md +99 -0
- package/examples/agents/.claude/skills/developer-experience/SKILL.md +99 -0
- package/examples/agents/.claude/skills/devops-cicd/SKILL.md +96 -0
- package/examples/agents/.claude/skills/full-stack-development/SKILL.md +90 -0
- package/examples/agents/.claude/skills/knowledge-management/SKILL.md +100 -0
- package/examples/agents/.claude/skills/pattern-generalization/SKILL.md +102 -0
- package/examples/agents/.claude/skills/sre-practices/SKILL.md +117 -0
- package/examples/agents/.claude/skills/technical-debt-management/SKILL.md +123 -0
- package/examples/agents/.claude/skills/technical-writing/SKILL.md +129 -0
- package/examples/agents/.github/agents/se-platform-code.agent.md +181 -0
- package/examples/agents/.github/agents/se-platform-plan.agent.md +178 -0
- package/examples/agents/.github/agents/se-platform-review.agent.md +113 -0
- package/examples/agents/.vscode/settings.json +8 -0
- package/examples/behaviours/_index.yaml +8 -0
- package/examples/behaviours/outcome_ownership.yaml +44 -0
- package/examples/behaviours/polymathic_knowledge.yaml +42 -0
- package/examples/behaviours/precise_communication.yaml +40 -0
- package/examples/behaviours/relentless_curiosity.yaml +38 -0
- package/examples/behaviours/systems_thinking.yaml +41 -0
- package/examples/capabilities/_index.yaml +8 -0
- package/examples/capabilities/business.yaml +251 -0
- package/examples/capabilities/delivery.yaml +352 -0
- package/examples/capabilities/people.yaml +100 -0
- package/examples/capabilities/reliability.yaml +318 -0
- package/examples/capabilities/scale.yaml +394 -0
- package/examples/disciplines/_index.yaml +5 -0
- package/examples/disciplines/data_engineering.yaml +76 -0
- package/examples/disciplines/software_engineering.yaml +76 -0
- package/examples/drivers.yaml +205 -0
- package/examples/framework.yaml +58 -0
- package/examples/grades.yaml +118 -0
- package/examples/questions/behaviours/outcome_ownership.yaml +52 -0
- package/examples/questions/behaviours/polymathic_knowledge.yaml +48 -0
- package/examples/questions/behaviours/precise_communication.yaml +55 -0
- package/examples/questions/behaviours/relentless_curiosity.yaml +51 -0
- package/examples/questions/behaviours/systems_thinking.yaml +53 -0
- package/examples/questions/skills/architecture_design.yaml +54 -0
- package/examples/questions/skills/cloud_platforms.yaml +48 -0
- package/examples/questions/skills/code_quality.yaml +49 -0
- package/examples/questions/skills/data_modeling.yaml +46 -0
- package/examples/questions/skills/devops.yaml +47 -0
- package/examples/questions/skills/full_stack_development.yaml +48 -0
- package/examples/questions/skills/sre_practices.yaml +44 -0
- package/examples/questions/skills/stakeholder_management.yaml +49 -0
- package/examples/questions/skills/team_collaboration.yaml +43 -0
- package/examples/questions/skills/technical_writing.yaml +43 -0
- package/examples/self-assessments.yaml +66 -0
- package/examples/stages.yaml +76 -0
- package/examples/tracks/_index.yaml +6 -0
- package/examples/tracks/manager.yaml +53 -0
- package/examples/tracks/platform.yaml +54 -0
- package/examples/tracks/sre.yaml +58 -0
- package/examples/vscode-settings.yaml +22 -0
- package/package.json +68 -0
|
@@ -0,0 +1,823 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent builder page
|
|
3
|
+
*
|
|
4
|
+
* Single scrollable view for generating AI coding agent configurations.
|
|
5
|
+
* Uses dropdown pattern matching job builder: discipline × track × stage.
|
|
6
|
+
* Stage includes "All Stages" option for complete deployment downloads.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
render,
|
|
11
|
+
div,
|
|
12
|
+
h1,
|
|
13
|
+
h2,
|
|
14
|
+
h3,
|
|
15
|
+
p,
|
|
16
|
+
span,
|
|
17
|
+
label,
|
|
18
|
+
section,
|
|
19
|
+
} from "../lib/render.js";
|
|
20
|
+
import { getState } from "../lib/state.js";
|
|
21
|
+
import { loadAgentDataBrowser } from "../lib/yaml-loader.js";
|
|
22
|
+
import {
|
|
23
|
+
generateStageAgentProfile,
|
|
24
|
+
deriveStageAgent,
|
|
25
|
+
generateSkillMd,
|
|
26
|
+
deriveAgentSkills,
|
|
27
|
+
deriveReferenceGrade,
|
|
28
|
+
} from "../model/agent.js";
|
|
29
|
+
import { createSelectWithValue } from "../lib/form-controls.js";
|
|
30
|
+
import { createReactive } from "../lib/reactive.js";
|
|
31
|
+
import { getStageEmoji } from "../formatters/stage/shared.js";
|
|
32
|
+
import { formatAgentProfile } from "../formatters/agent/profile.js";
|
|
33
|
+
import { formatAgentSkill } from "../formatters/agent/skill.js";
|
|
34
|
+
|
|
35
|
+
/** All stages option value */
|
|
36
|
+
const ALL_STAGES_VALUE = "all";
|
|
37
|
+
|
|
38
|
+
/** @type {Object|null} Cached agent data */
|
|
39
|
+
let agentDataCache = null;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Load agent data with caching
|
|
43
|
+
* @param {string} dataDir - Data directory path
|
|
44
|
+
* @returns {Promise<Object>}
|
|
45
|
+
*/
|
|
46
|
+
async function getAgentData(dataDir = "./data") {
|
|
47
|
+
if (!agentDataCache) {
|
|
48
|
+
agentDataCache = await loadAgentDataBrowser(dataDir);
|
|
49
|
+
}
|
|
50
|
+
return agentDataCache;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Render agent builder page
|
|
55
|
+
*/
|
|
56
|
+
export async function renderAgentBuilder() {
|
|
57
|
+
const { data } = getState();
|
|
58
|
+
|
|
59
|
+
// Show loading state
|
|
60
|
+
render(
|
|
61
|
+
div(
|
|
62
|
+
{ className: "agent-builder-page wide" },
|
|
63
|
+
div({ className: "loading" }, p({}, "Loading agent definitions...")),
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Load agent-specific data
|
|
68
|
+
const agentData = await getAgentData();
|
|
69
|
+
|
|
70
|
+
// Filter to only disciplines/tracks that have agent definitions
|
|
71
|
+
const agentDisciplineIds = new Set(agentData.disciplines.map((d) => d.id));
|
|
72
|
+
const agentTrackIds = new Set(agentData.tracks.map((t) => t.id));
|
|
73
|
+
|
|
74
|
+
const availableDisciplines = data.disciplines.filter((d) =>
|
|
75
|
+
agentDisciplineIds.has(d.id),
|
|
76
|
+
);
|
|
77
|
+
const availableTracks = data.tracks.filter((t) => agentTrackIds.has(t.id));
|
|
78
|
+
const stages = data.stages || [];
|
|
79
|
+
|
|
80
|
+
// Build stage options with "All Stages" first
|
|
81
|
+
const stageOptions = [
|
|
82
|
+
{ id: ALL_STAGES_VALUE, name: "All Stages" },
|
|
83
|
+
...stages.map((s) => ({
|
|
84
|
+
id: s.id,
|
|
85
|
+
name: `${getStageEmoji(stages, s.id)} ${s.name}`,
|
|
86
|
+
})),
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
// Parse URL params for pre-selection
|
|
90
|
+
const hash = window.location.hash;
|
|
91
|
+
const pathMatch = hash.match(/#\/agent\/([^/]+)\/([^/]+)(?:\/([^/?]+))?/);
|
|
92
|
+
const initialDiscipline = pathMatch ? pathMatch[1] : "";
|
|
93
|
+
const initialTrack = pathMatch ? pathMatch[2] : "";
|
|
94
|
+
const initialStage =
|
|
95
|
+
pathMatch && pathMatch[3] ? pathMatch[3] : ALL_STAGES_VALUE;
|
|
96
|
+
|
|
97
|
+
// Create reactive selection state
|
|
98
|
+
const selection = createReactive({
|
|
99
|
+
discipline: initialDiscipline,
|
|
100
|
+
track: initialTrack,
|
|
101
|
+
stage: initialStage,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Preview container - will be updated reactively
|
|
105
|
+
const previewContainer = div(
|
|
106
|
+
{ className: "agent-preview" },
|
|
107
|
+
createEmptyState(availableDisciplines.length, availableTracks.length),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Update the preview when selection changes
|
|
112
|
+
* @param {Object} sel - Current selection
|
|
113
|
+
*/
|
|
114
|
+
function updatePreview({ discipline, track, stage }) {
|
|
115
|
+
// Update URL without triggering navigation
|
|
116
|
+
if (discipline && track) {
|
|
117
|
+
const stagePart = stage && stage !== ALL_STAGES_VALUE ? `/${stage}` : "";
|
|
118
|
+
const newHash = `#/agent/${discipline}/${track}${stagePart}`;
|
|
119
|
+
if (window.location.hash !== newHash) {
|
|
120
|
+
history.replaceState(null, "", newHash);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
previewContainer.innerHTML = "";
|
|
125
|
+
|
|
126
|
+
if (!discipline || !track) {
|
|
127
|
+
previewContainer.appendChild(
|
|
128
|
+
createEmptyState(availableDisciplines.length, availableTracks.length),
|
|
129
|
+
);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Get full objects
|
|
134
|
+
const humanDiscipline = data.disciplines.find((d) => d.id === discipline);
|
|
135
|
+
const humanTrack = data.tracks.find((t) => t.id === track);
|
|
136
|
+
const agentDiscipline = agentData.disciplines.find(
|
|
137
|
+
(d) => d.id === discipline,
|
|
138
|
+
);
|
|
139
|
+
const agentTrack = agentData.tracks.find((t) => t.id === track);
|
|
140
|
+
|
|
141
|
+
if (!humanDiscipline || !humanTrack || !agentDiscipline || !agentTrack) {
|
|
142
|
+
previewContainer.appendChild(
|
|
143
|
+
div(
|
|
144
|
+
{ className: "empty-state" },
|
|
145
|
+
p({ className: "text-muted" }, "Invalid combination selected."),
|
|
146
|
+
),
|
|
147
|
+
);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Get reference grade for derivation
|
|
152
|
+
const grade = deriveReferenceGrade(data.grades);
|
|
153
|
+
|
|
154
|
+
// Build context for generation
|
|
155
|
+
const context = {
|
|
156
|
+
humanDiscipline,
|
|
157
|
+
humanTrack,
|
|
158
|
+
agentDiscipline,
|
|
159
|
+
agentTrack,
|
|
160
|
+
grade,
|
|
161
|
+
stages,
|
|
162
|
+
skills: data.skills,
|
|
163
|
+
behaviours: data.behaviours,
|
|
164
|
+
agentBehaviours: agentData.behaviours,
|
|
165
|
+
capabilities: data.capabilities,
|
|
166
|
+
vscodeSettings: agentData.vscodeSettings,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Generate preview based on stage selection
|
|
170
|
+
if (stage === ALL_STAGES_VALUE) {
|
|
171
|
+
previewContainer.appendChild(createAllStagesPreview(context));
|
|
172
|
+
} else {
|
|
173
|
+
const stageObj = stages.find((s) => s.id === stage);
|
|
174
|
+
if (!stageObj) {
|
|
175
|
+
previewContainer.appendChild(
|
|
176
|
+
div(
|
|
177
|
+
{ className: "empty-state" },
|
|
178
|
+
p({ className: "text-muted" }, `Stage "${stage}" not found.`),
|
|
179
|
+
),
|
|
180
|
+
);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
previewContainer.appendChild(createSingleStagePreview(context, stageObj));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Subscribe to selection changes
|
|
188
|
+
selection.subscribe(updatePreview);
|
|
189
|
+
|
|
190
|
+
// Build the page
|
|
191
|
+
const page = div(
|
|
192
|
+
{ className: "agent-builder-page wide" },
|
|
193
|
+
// Header
|
|
194
|
+
div(
|
|
195
|
+
{ className: "page-header" },
|
|
196
|
+
h1({ className: "page-title" }, "🤖 Agent Builder"),
|
|
197
|
+
p(
|
|
198
|
+
{ className: "page-description" },
|
|
199
|
+
"Generate AI coding agents from discipline × track × stage combinations. " +
|
|
200
|
+
"Export complete agent profiles and skill files for GitHub Copilot.",
|
|
201
|
+
),
|
|
202
|
+
),
|
|
203
|
+
|
|
204
|
+
// Form section
|
|
205
|
+
div(
|
|
206
|
+
{ className: "agent-builder-form" },
|
|
207
|
+
h2({}, "Select Components"),
|
|
208
|
+
div(
|
|
209
|
+
{ className: "auto-grid-sm gap-lg" },
|
|
210
|
+
// Discipline selector
|
|
211
|
+
div(
|
|
212
|
+
{ className: "form-group" },
|
|
213
|
+
label({ className: "form-label" }, "Discipline"),
|
|
214
|
+
availableDisciplines.length > 0
|
|
215
|
+
? createSelectWithValue({
|
|
216
|
+
id: "agent-discipline-select",
|
|
217
|
+
items: availableDisciplines,
|
|
218
|
+
initialValue: selection.get().discipline,
|
|
219
|
+
placeholder: "Select a discipline...",
|
|
220
|
+
onChange: (value) => {
|
|
221
|
+
selection.update((prev) => ({ ...prev, discipline: value }));
|
|
222
|
+
},
|
|
223
|
+
getDisplayName: (d) => d.specialization || d.name,
|
|
224
|
+
})
|
|
225
|
+
: p(
|
|
226
|
+
{ className: "text-muted" },
|
|
227
|
+
"No disciplines have agent definitions.",
|
|
228
|
+
),
|
|
229
|
+
),
|
|
230
|
+
// Track selector
|
|
231
|
+
div(
|
|
232
|
+
{ className: "form-group" },
|
|
233
|
+
label({ className: "form-label" }, "Track"),
|
|
234
|
+
availableTracks.length > 0
|
|
235
|
+
? createSelectWithValue({
|
|
236
|
+
id: "agent-track-select",
|
|
237
|
+
items: availableTracks,
|
|
238
|
+
initialValue: selection.get().track,
|
|
239
|
+
placeholder: "Select a track...",
|
|
240
|
+
onChange: (value) => {
|
|
241
|
+
selection.update((prev) => ({ ...prev, track: value }));
|
|
242
|
+
},
|
|
243
|
+
getDisplayName: (t) => t.name,
|
|
244
|
+
})
|
|
245
|
+
: p(
|
|
246
|
+
{ className: "text-muted" },
|
|
247
|
+
"No tracks have agent definitions.",
|
|
248
|
+
),
|
|
249
|
+
),
|
|
250
|
+
// Stage selector (dropdown with All Stages option)
|
|
251
|
+
div(
|
|
252
|
+
{ className: "form-group" },
|
|
253
|
+
label({ className: "form-label" }, "Stage"),
|
|
254
|
+
createSelectWithValue({
|
|
255
|
+
id: "agent-stage-select",
|
|
256
|
+
items: stageOptions,
|
|
257
|
+
initialValue: selection.get().stage,
|
|
258
|
+
placeholder: "Select a stage...",
|
|
259
|
+
onChange: (value) => {
|
|
260
|
+
selection.update((prev) => ({ ...prev, stage: value }));
|
|
261
|
+
},
|
|
262
|
+
getDisplayName: (s) => s.name,
|
|
263
|
+
}),
|
|
264
|
+
),
|
|
265
|
+
),
|
|
266
|
+
),
|
|
267
|
+
|
|
268
|
+
// Preview section
|
|
269
|
+
previewContainer,
|
|
270
|
+
|
|
271
|
+
// Help section
|
|
272
|
+
createHelpSection(),
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
render(page);
|
|
276
|
+
|
|
277
|
+
// Trigger initial update if pre-selected
|
|
278
|
+
if (initialDiscipline && initialTrack) {
|
|
279
|
+
updatePreview(selection.get());
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Create empty state message
|
|
285
|
+
* @param {number} disciplineCount - Number of available disciplines
|
|
286
|
+
* @param {number} trackCount - Number of available tracks
|
|
287
|
+
* @returns {HTMLElement}
|
|
288
|
+
*/
|
|
289
|
+
function createEmptyState(disciplineCount, trackCount) {
|
|
290
|
+
if (disciplineCount === 0 || trackCount === 0) {
|
|
291
|
+
return div(
|
|
292
|
+
{ className: "empty-state" },
|
|
293
|
+
p(
|
|
294
|
+
{ className: "text-muted" },
|
|
295
|
+
"No agent definitions found. Add agent.yaml files to disciplines and tracks.",
|
|
296
|
+
),
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return div(
|
|
301
|
+
{ className: "empty-state" },
|
|
302
|
+
p(
|
|
303
|
+
{ className: "text-muted" },
|
|
304
|
+
"Select a discipline, track, and stage to generate agents.",
|
|
305
|
+
),
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Create preview for all stages
|
|
311
|
+
* Shows cards for each stage agent and all skills
|
|
312
|
+
* @param {Object} context - Generation context
|
|
313
|
+
* @returns {HTMLElement}
|
|
314
|
+
*/
|
|
315
|
+
function createAllStagesPreview(context) {
|
|
316
|
+
const {
|
|
317
|
+
humanDiscipline,
|
|
318
|
+
humanTrack,
|
|
319
|
+
agentDiscipline,
|
|
320
|
+
agentTrack,
|
|
321
|
+
grade,
|
|
322
|
+
stages,
|
|
323
|
+
skills,
|
|
324
|
+
behaviours,
|
|
325
|
+
agentBehaviours,
|
|
326
|
+
capabilities,
|
|
327
|
+
vscodeSettings,
|
|
328
|
+
} = context;
|
|
329
|
+
|
|
330
|
+
// Generate all stage agents
|
|
331
|
+
const stageAgents = stages.map((stage) => {
|
|
332
|
+
const derived = deriveStageAgent({
|
|
333
|
+
discipline: humanDiscipline,
|
|
334
|
+
track: humanTrack,
|
|
335
|
+
stage,
|
|
336
|
+
grade,
|
|
337
|
+
skills,
|
|
338
|
+
behaviours,
|
|
339
|
+
agentBehaviours,
|
|
340
|
+
agentDiscipline,
|
|
341
|
+
agentTrack,
|
|
342
|
+
capabilities,
|
|
343
|
+
stages,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const profile = generateStageAgentProfile({
|
|
347
|
+
discipline: humanDiscipline,
|
|
348
|
+
track: humanTrack,
|
|
349
|
+
stage,
|
|
350
|
+
grade,
|
|
351
|
+
skills,
|
|
352
|
+
behaviours,
|
|
353
|
+
agentBehaviours,
|
|
354
|
+
agentDiscipline,
|
|
355
|
+
agentTrack,
|
|
356
|
+
capabilities,
|
|
357
|
+
stages,
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
return { stage, derived, profile };
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// Get derived skills for skill cards
|
|
364
|
+
const derivedSkills = deriveAgentSkills({
|
|
365
|
+
discipline: humanDiscipline,
|
|
366
|
+
track: humanTrack,
|
|
367
|
+
grade,
|
|
368
|
+
skills,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Generate skill files
|
|
372
|
+
const skillFiles = derivedSkills
|
|
373
|
+
.map((derived) => skills.find((s) => s.id === derived.skillId))
|
|
374
|
+
.filter((skill) => skill?.agent)
|
|
375
|
+
.map((skill) => generateSkillMd(skill));
|
|
376
|
+
|
|
377
|
+
return div(
|
|
378
|
+
{ className: "agent-deployment" },
|
|
379
|
+
|
|
380
|
+
// Download all button
|
|
381
|
+
createDownloadAllButton(stageAgents, skillFiles, vscodeSettings, context),
|
|
382
|
+
|
|
383
|
+
// Agents section
|
|
384
|
+
section(
|
|
385
|
+
{ className: "agent-section" },
|
|
386
|
+
h2({}, `Agents (${stageAgents.length})`),
|
|
387
|
+
p(
|
|
388
|
+
{ className: "text-muted" },
|
|
389
|
+
"Stage-specific agents with appropriate tools, constraints, and handoffs.",
|
|
390
|
+
),
|
|
391
|
+
div(
|
|
392
|
+
{ className: "agent-cards-grid" },
|
|
393
|
+
...stageAgents.map(({ stage, profile }) =>
|
|
394
|
+
createAgentCard(stage, profile, stages),
|
|
395
|
+
),
|
|
396
|
+
),
|
|
397
|
+
),
|
|
398
|
+
|
|
399
|
+
// Skills section
|
|
400
|
+
section(
|
|
401
|
+
{ className: "agent-section" },
|
|
402
|
+
h2({}, `Skills (${skillFiles.length})`),
|
|
403
|
+
skillFiles.length > 0
|
|
404
|
+
? div(
|
|
405
|
+
{ className: "skill-cards-grid" },
|
|
406
|
+
...skillFiles.map((skill) => createSkillCard(skill)),
|
|
407
|
+
)
|
|
408
|
+
: p(
|
|
409
|
+
{ className: "text-muted" },
|
|
410
|
+
"No skills with agent sections found for this discipline.",
|
|
411
|
+
),
|
|
412
|
+
),
|
|
413
|
+
|
|
414
|
+
// CLI hint
|
|
415
|
+
createCliHint(humanDiscipline.id, humanTrack.id),
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Create preview for a single stage
|
|
421
|
+
* @param {Object} context - Generation context
|
|
422
|
+
* @param {Object} stage - Selected stage
|
|
423
|
+
* @returns {HTMLElement}
|
|
424
|
+
*/
|
|
425
|
+
function createSingleStagePreview(context, stage) {
|
|
426
|
+
const {
|
|
427
|
+
humanDiscipline,
|
|
428
|
+
humanTrack,
|
|
429
|
+
agentDiscipline,
|
|
430
|
+
agentTrack,
|
|
431
|
+
grade,
|
|
432
|
+
skills,
|
|
433
|
+
behaviours,
|
|
434
|
+
agentBehaviours,
|
|
435
|
+
capabilities,
|
|
436
|
+
vscodeSettings,
|
|
437
|
+
stages,
|
|
438
|
+
} = context;
|
|
439
|
+
|
|
440
|
+
// Derive stage agent
|
|
441
|
+
const derived = deriveStageAgent({
|
|
442
|
+
discipline: humanDiscipline,
|
|
443
|
+
track: humanTrack,
|
|
444
|
+
stage,
|
|
445
|
+
grade,
|
|
446
|
+
skills,
|
|
447
|
+
behaviours,
|
|
448
|
+
agentBehaviours,
|
|
449
|
+
agentDiscipline,
|
|
450
|
+
agentTrack,
|
|
451
|
+
capabilities,
|
|
452
|
+
stages,
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
const profile = generateStageAgentProfile({
|
|
456
|
+
discipline: humanDiscipline,
|
|
457
|
+
track: humanTrack,
|
|
458
|
+
stage,
|
|
459
|
+
grade,
|
|
460
|
+
skills,
|
|
461
|
+
behaviours,
|
|
462
|
+
agentBehaviours,
|
|
463
|
+
agentDiscipline,
|
|
464
|
+
agentTrack,
|
|
465
|
+
capabilities,
|
|
466
|
+
stages,
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Get skills for this stage (using full derived skills)
|
|
470
|
+
const derivedSkills = deriveAgentSkills({
|
|
471
|
+
discipline: humanDiscipline,
|
|
472
|
+
track: humanTrack,
|
|
473
|
+
grade,
|
|
474
|
+
skills,
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
const skillFiles = derivedSkills
|
|
478
|
+
.map((d) => skills.find((s) => s.id === d.skillId))
|
|
479
|
+
.filter((skill) => skill?.agent)
|
|
480
|
+
.map((skill) => generateSkillMd(skill));
|
|
481
|
+
|
|
482
|
+
return div(
|
|
483
|
+
{ className: "agent-deployment" },
|
|
484
|
+
|
|
485
|
+
// Download button for single stage
|
|
486
|
+
createDownloadSingleButton(profile, skillFiles, vscodeSettings),
|
|
487
|
+
|
|
488
|
+
// Agents section (single card)
|
|
489
|
+
section(
|
|
490
|
+
{ className: "agent-section" },
|
|
491
|
+
h2({}, "Agent"),
|
|
492
|
+
div(
|
|
493
|
+
{ className: "agent-cards-grid single" },
|
|
494
|
+
createAgentCard(stage, profile, stages, derived),
|
|
495
|
+
),
|
|
496
|
+
),
|
|
497
|
+
|
|
498
|
+
// Skills section
|
|
499
|
+
section(
|
|
500
|
+
{ className: "agent-section" },
|
|
501
|
+
h2({}, `Skills (${skillFiles.length})`),
|
|
502
|
+
skillFiles.length > 0
|
|
503
|
+
? div(
|
|
504
|
+
{ className: "skill-cards-grid" },
|
|
505
|
+
...skillFiles.map((skill) => createSkillCard(skill)),
|
|
506
|
+
)
|
|
507
|
+
: p(
|
|
508
|
+
{ className: "text-muted" },
|
|
509
|
+
"No skills with agent sections found for this discipline.",
|
|
510
|
+
),
|
|
511
|
+
),
|
|
512
|
+
|
|
513
|
+
// CLI hint
|
|
514
|
+
createCliHint(humanDiscipline.id, humanTrack.id, stage.id),
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Create an agent card for a stage
|
|
520
|
+
* @param {Object} stage - Stage object
|
|
521
|
+
* @param {Object} profile - Generated profile
|
|
522
|
+
* @param {Array} stages - All stages for emoji lookup
|
|
523
|
+
* @param {Object} [_derived] - Optional derived agent data for extra info
|
|
524
|
+
* @returns {HTMLElement}
|
|
525
|
+
*/
|
|
526
|
+
function createAgentCard(stage, profile, stages, _derived) {
|
|
527
|
+
const content = formatAgentProfile(profile);
|
|
528
|
+
const stageEmoji = getStageEmoji(stages, stage.id);
|
|
529
|
+
|
|
530
|
+
const card = div(
|
|
531
|
+
{ className: "agent-card" },
|
|
532
|
+
div(
|
|
533
|
+
{ className: "agent-card-header" },
|
|
534
|
+
div(
|
|
535
|
+
{ className: "agent-card-title" },
|
|
536
|
+
span({ className: "agent-card-emoji" }, stageEmoji),
|
|
537
|
+
h3({}, `${stage.name} Agent`),
|
|
538
|
+
),
|
|
539
|
+
createCopyButton(content),
|
|
540
|
+
),
|
|
541
|
+
p({ className: "agent-card-filename" }, profile.filename),
|
|
542
|
+
div({ className: "agent-card-preview" }, createCodePreview(content)),
|
|
543
|
+
);
|
|
544
|
+
|
|
545
|
+
return card;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Create a skill card
|
|
550
|
+
* @param {Object} skill - Skill with frontmatter and body
|
|
551
|
+
* @returns {HTMLElement}
|
|
552
|
+
*/
|
|
553
|
+
function createSkillCard(skill) {
|
|
554
|
+
const content = formatAgentSkill(skill);
|
|
555
|
+
const filename = `${skill.dirname}/SKILL.md`;
|
|
556
|
+
|
|
557
|
+
return div(
|
|
558
|
+
{ className: "skill-card" },
|
|
559
|
+
div(
|
|
560
|
+
{ className: "skill-card-header" },
|
|
561
|
+
span({ className: "skill-card-name" }, skill.frontmatter.name),
|
|
562
|
+
createCopyButton(content),
|
|
563
|
+
),
|
|
564
|
+
p({ className: "skill-card-filename" }, filename),
|
|
565
|
+
div({ className: "skill-card-preview" }, createCodePreview(content)),
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Create a code preview element
|
|
571
|
+
* @param {string} content - Code content
|
|
572
|
+
* @returns {HTMLElement}
|
|
573
|
+
*/
|
|
574
|
+
function createCodePreview(content) {
|
|
575
|
+
const pre = document.createElement("pre");
|
|
576
|
+
pre.className = "code-block code-preview";
|
|
577
|
+
|
|
578
|
+
const code = document.createElement("code");
|
|
579
|
+
code.textContent = content;
|
|
580
|
+
|
|
581
|
+
pre.appendChild(code);
|
|
582
|
+
return pre;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Create a copy button
|
|
587
|
+
* @param {string} content - Content to copy
|
|
588
|
+
* @returns {HTMLElement}
|
|
589
|
+
*/
|
|
590
|
+
function createCopyButton(content) {
|
|
591
|
+
const btn = document.createElement("button");
|
|
592
|
+
btn.className = "btn btn-sm copy-btn";
|
|
593
|
+
btn.textContent = "📋 Copy";
|
|
594
|
+
|
|
595
|
+
btn.addEventListener("click", async () => {
|
|
596
|
+
try {
|
|
597
|
+
await navigator.clipboard.writeText(content);
|
|
598
|
+
btn.textContent = "✓ Copied";
|
|
599
|
+
setTimeout(() => {
|
|
600
|
+
btn.textContent = "📋 Copy";
|
|
601
|
+
}, 2000);
|
|
602
|
+
} catch {
|
|
603
|
+
btn.textContent = "Failed";
|
|
604
|
+
setTimeout(() => {
|
|
605
|
+
btn.textContent = "📋 Copy";
|
|
606
|
+
}, 2000);
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
return btn;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Create download all button for all stages
|
|
615
|
+
* @param {Array} stageAgents - Array of {stage, derived, profile}
|
|
616
|
+
* @param {Array} skillFiles - Array of skill file objects
|
|
617
|
+
* @param {Object} vscodeSettings - VS Code settings
|
|
618
|
+
* @param {Object} context - Context with discipline/track info
|
|
619
|
+
* @returns {HTMLElement}
|
|
620
|
+
*/
|
|
621
|
+
function createDownloadAllButton(
|
|
622
|
+
stageAgents,
|
|
623
|
+
skillFiles,
|
|
624
|
+
vscodeSettings,
|
|
625
|
+
context,
|
|
626
|
+
) {
|
|
627
|
+
const { humanDiscipline, humanTrack } = context;
|
|
628
|
+
const agentName = `${humanDiscipline.id}-${humanTrack.id}`.replace(/_/g, "-");
|
|
629
|
+
|
|
630
|
+
const btn = document.createElement("button");
|
|
631
|
+
btn.className = "btn btn-primary download-all-btn";
|
|
632
|
+
btn.textContent = "📦 Download All (.zip)";
|
|
633
|
+
|
|
634
|
+
btn.addEventListener("click", async () => {
|
|
635
|
+
btn.disabled = true;
|
|
636
|
+
btn.textContent = "Generating...";
|
|
637
|
+
|
|
638
|
+
try {
|
|
639
|
+
const JSZip = await importJSZip();
|
|
640
|
+
const zip = new JSZip();
|
|
641
|
+
|
|
642
|
+
// Add all stage agent profiles
|
|
643
|
+
for (const { profile } of stageAgents) {
|
|
644
|
+
const content = formatAgentProfile(profile);
|
|
645
|
+
zip.file(`.github/agents/${profile.filename}`, content);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Add skills
|
|
649
|
+
for (const skill of skillFiles) {
|
|
650
|
+
const content = formatAgentSkill(skill);
|
|
651
|
+
zip.file(`.claude/skills/${skill.dirname}/SKILL.md`, content);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Add VS Code settings
|
|
655
|
+
if (Object.keys(vscodeSettings).length > 0) {
|
|
656
|
+
zip.file(
|
|
657
|
+
".vscode/settings.json",
|
|
658
|
+
JSON.stringify(vscodeSettings, null, 2) + "\n",
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// Generate and download
|
|
663
|
+
const blob = await zip.generateAsync({ type: "blob" });
|
|
664
|
+
const url = URL.createObjectURL(blob);
|
|
665
|
+
|
|
666
|
+
const link = document.createElement("a");
|
|
667
|
+
link.href = url;
|
|
668
|
+
link.download = `${agentName}-agents.zip`;
|
|
669
|
+
document.body.appendChild(link);
|
|
670
|
+
link.click();
|
|
671
|
+
document.body.removeChild(link);
|
|
672
|
+
|
|
673
|
+
URL.revokeObjectURL(url);
|
|
674
|
+
} finally {
|
|
675
|
+
btn.disabled = false;
|
|
676
|
+
btn.textContent = "📦 Download All (.zip)";
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
return btn;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Create download button for single stage
|
|
685
|
+
* @param {Object} profile - Agent profile
|
|
686
|
+
* @param {Array} skillFiles - Skill files
|
|
687
|
+
* @param {Object} vscodeSettings - VS Code settings
|
|
688
|
+
* @returns {HTMLElement}
|
|
689
|
+
*/
|
|
690
|
+
function createDownloadSingleButton(profile, skillFiles, vscodeSettings) {
|
|
691
|
+
const btn = document.createElement("button");
|
|
692
|
+
btn.className = "btn btn-primary download-all-btn";
|
|
693
|
+
btn.textContent = "📥 Download Agent (.zip)";
|
|
694
|
+
|
|
695
|
+
btn.addEventListener("click", async () => {
|
|
696
|
+
btn.disabled = true;
|
|
697
|
+
btn.textContent = "Generating...";
|
|
698
|
+
|
|
699
|
+
try {
|
|
700
|
+
const JSZip = await importJSZip();
|
|
701
|
+
const zip = new JSZip();
|
|
702
|
+
|
|
703
|
+
// Add profile
|
|
704
|
+
const content = formatAgentProfile(profile);
|
|
705
|
+
zip.file(`.github/agents/${profile.filename}`, content);
|
|
706
|
+
|
|
707
|
+
// Add skills
|
|
708
|
+
for (const skill of skillFiles) {
|
|
709
|
+
const skillContent = formatAgentSkill(skill);
|
|
710
|
+
zip.file(`.claude/skills/${skill.dirname}/SKILL.md`, skillContent);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Add VS Code settings
|
|
714
|
+
if (Object.keys(vscodeSettings).length > 0) {
|
|
715
|
+
zip.file(
|
|
716
|
+
".vscode/settings.json",
|
|
717
|
+
JSON.stringify(vscodeSettings, null, 2) + "\n",
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Generate and download
|
|
722
|
+
const blob = await zip.generateAsync({ type: "blob" });
|
|
723
|
+
const url = URL.createObjectURL(blob);
|
|
724
|
+
|
|
725
|
+
const link = document.createElement("a");
|
|
726
|
+
link.href = url;
|
|
727
|
+
link.download = `${profile.frontmatter.name}-agent.zip`;
|
|
728
|
+
document.body.appendChild(link);
|
|
729
|
+
link.click();
|
|
730
|
+
document.body.removeChild(link);
|
|
731
|
+
|
|
732
|
+
URL.revokeObjectURL(url);
|
|
733
|
+
} finally {
|
|
734
|
+
btn.disabled = false;
|
|
735
|
+
btn.textContent = "📥 Download Agent (.zip)";
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
return btn;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Dynamically import JSZip from CDN
|
|
744
|
+
* @returns {Promise<typeof JSZip>}
|
|
745
|
+
*/
|
|
746
|
+
async function importJSZip() {
|
|
747
|
+
const module = await import("https://cdn.jsdelivr.net/npm/jszip@3.10.1/+esm");
|
|
748
|
+
return module.default;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Create CLI hint section
|
|
753
|
+
* @param {string} disciplineId - Discipline ID
|
|
754
|
+
* @param {string} trackId - Track ID
|
|
755
|
+
* @param {string} [stageId] - Optional stage ID
|
|
756
|
+
* @returns {HTMLElement}
|
|
757
|
+
*/
|
|
758
|
+
function createCliHint(disciplineId, trackId, stageId) {
|
|
759
|
+
const stageArg = stageId ? ` --stage=${stageId}` : "";
|
|
760
|
+
const command = `npx pathway agent ${disciplineId} ${trackId}${stageArg} --output=.github`;
|
|
761
|
+
|
|
762
|
+
const container = section(
|
|
763
|
+
{ className: "agent-section cli-hint" },
|
|
764
|
+
h2({}, "CLI Alternative"),
|
|
765
|
+
p({}, "Generate this agent from the command line:"),
|
|
766
|
+
div(
|
|
767
|
+
{ className: "cli-command" },
|
|
768
|
+
createCodePreview(command),
|
|
769
|
+
createCopyButton(command),
|
|
770
|
+
),
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
return container;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Create help section explaining how agent builder works
|
|
778
|
+
* @returns {HTMLElement}
|
|
779
|
+
*/
|
|
780
|
+
function createHelpSection() {
|
|
781
|
+
return section(
|
|
782
|
+
{ className: "section section-detail" },
|
|
783
|
+
h2({ className: "section-title" }, "How It Works"),
|
|
784
|
+
div(
|
|
785
|
+
{ className: "auto-grid-md" },
|
|
786
|
+
div(
|
|
787
|
+
{ className: "detail-item" },
|
|
788
|
+
div({ className: "detail-item-label" }, "Stages"),
|
|
789
|
+
p(
|
|
790
|
+
{},
|
|
791
|
+
"Agents are generated for each stage: Plan (research), Code (implement), and Review (verify). " +
|
|
792
|
+
"Each stage has specific tools, constraints, and handoffs.",
|
|
793
|
+
),
|
|
794
|
+
),
|
|
795
|
+
div(
|
|
796
|
+
{ className: "detail-item" },
|
|
797
|
+
div({ className: "detail-item-label" }, "Agent Profiles"),
|
|
798
|
+
p(
|
|
799
|
+
{},
|
|
800
|
+
"The .agent.md files contain the agent's identity, capabilities, and constraints. " +
|
|
801
|
+
"Place them in .github/agents/ to register with GitHub Copilot.",
|
|
802
|
+
),
|
|
803
|
+
),
|
|
804
|
+
div(
|
|
805
|
+
{ className: "detail-item" },
|
|
806
|
+
div({ className: "detail-item-label" }, "Skills"),
|
|
807
|
+
p(
|
|
808
|
+
{},
|
|
809
|
+
"SKILL.md files provide specialized knowledge that agents can use. " +
|
|
810
|
+
"Place them in .claude/skills/{skill-name}/ directories.",
|
|
811
|
+
),
|
|
812
|
+
),
|
|
813
|
+
div(
|
|
814
|
+
{ className: "detail-item" },
|
|
815
|
+
div({ className: "detail-item-label" }, "All Stages"),
|
|
816
|
+
p(
|
|
817
|
+
{},
|
|
818
|
+
"Select 'All Stages' to download a complete agent deployment with all stage agents and skills in one zip file.",
|
|
819
|
+
),
|
|
820
|
+
),
|
|
821
|
+
),
|
|
822
|
+
);
|
|
823
|
+
}
|