@mark-gozner/aigile-method 0.4.5
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.md +26 -0
- package/README.md +300 -0
- package/core/agent-teams/team-all.yaml +24 -0
- package/core/agent-teams/team-company.yaml +17 -0
- package/core/agent-teams/team-enterprise.yaml +17 -0
- package/core/agent-teams/team-fullstack.yaml +16 -0
- package/core/agent-teams/team-ide-minimal.yaml +10 -0
- package/core/agents/aigile-master.md +476 -0
- package/core/agents/aigile-orchestrator.agent.md +200 -0
- package/core/agents/analyst.md +45 -0
- package/core/agents/architect.md +43 -0
- package/core/agents/code-tour.agent.md +208 -0
- package/core/agents/dev.agent.md +145 -0
- package/core/agents/dev.md +130 -0
- package/core/agents/expert-react-frontend-engineer.agent.md +741 -0
- package/core/agents/pm.md +33 -0
- package/core/agents/po.md +35 -0
- package/core/agents/qa.md +38 -0
- package/core/agents/sm.md +31 -0
- package/core/agents/ui-expert.md +39 -0
- package/core/agents/ux-expert.md +31 -0
- package/core/checklists/architect-checklist.md +246 -0
- package/core/checklists/change-checklist.md +182 -0
- package/core/checklists/pm-checklist.md +286 -0
- package/core/checklists/po-master-checklist.md +291 -0
- package/core/checklists/story-dod-checklist.md +94 -0
- package/core/checklists/story-draft-checklist.md +153 -0
- package/core/core-config.yaml +22 -0
- package/core/data/aigile-kb.md +112 -0
- package/core/data/brainstorming-techniques.md +73 -0
- package/core/data/elicitation-methods.md +42 -0
- package/core/data/technical-preferences.md +52 -0
- package/core/data/test-levels-framework.md +43 -0
- package/core/data/test-priorities-matrix.md +26 -0
- package/core/instructions/csharp.instructions.md +656 -0
- package/core/instructions/dotnet/csharp.instructions.md +656 -0
- package/core/instructions/java/java.instructions.md +67 -0
- package/core/instructions/java/spring-boot.instructions.md +122 -0
- package/core/instructions/java.instructions.md +67 -0
- package/core/instructions/spring-boot.instructions.md +122 -0
- package/core/prompts/README.md +11 -0
- package/core/prompts/architecture/architecture-blueprint-generator.prompt.md +322 -0
- package/core/prompts/architecture/architecture-validation.prompt.md +71 -0
- package/core/prompts/architecture/file-tree-generator.prompt.md +405 -0
- package/core/prompts/architecture/technical-project-analyze.prompt.md +43 -0
- package/core/prompts/architecture-blueprint-generator.prompt.md +322 -0
- package/core/prompts/architecture-validation.prompt.md +71 -0
- package/core/prompts/code-review.prompt.md +107 -0
- package/core/prompts/confluence-in-md.prompt.md +167 -0
- package/core/prompts/copilot-instructions-blueprint-generator.prompt.md +294 -0
- package/core/prompts/create-implementation-plan.prompt.md +157 -0
- package/core/prompts/create-oo-component-documentation.prompt.md +193 -0
- package/core/prompts/file-tree-generator.prompt.md +405 -0
- package/core/prompts/generate-unit-tests.prompt.md +291 -0
- package/core/prompts/java/java-doc.prompt.md +24 -0
- package/core/prompts/java/java-junit.prompt.md +64 -0
- package/core/prompts/java/junit-5.prompt.md +64 -0
- package/core/prompts/java-doc.prompt.md +24 -0
- package/core/prompts/java-junit.prompt.md +64 -0
- package/core/prompts/junit-5.prompt.md +64 -0
- package/core/prompts/release-notes/README.md +11 -0
- package/core/prompts/release-notes/release-notes.prompt.md +723 -0
- package/core/prompts/release-notes.prompt.md +723 -0
- package/core/prompts/technical-project-analyze.prompt.md +43 -0
- package/core/tasks/advanced-elicitation.md +119 -0
- package/core/tasks/check-story-implemented.md +44 -0
- package/core/tasks/code-arch-review-with-github.md +40 -0
- package/core/tasks/create-architecture-doc.md +55 -0
- package/core/tasks/create-jira-epic-from-confluence.md +70 -0
- package/core/tasks/create-jira-story-from-confluence.md +39 -0
- package/core/tasks/create-jira-story-from-text.md +39 -0
- package/core/tasks/create-next-story.md +35 -0
- package/core/tasks/create-prd-doc.md +54 -0
- package/core/tasks/create-stories-from-epic.md +66 -0
- package/core/tasks/create-tasks-for-story.md +60 -0
- package/core/tasks/document-project.md +69 -0
- package/core/tasks/execute-checklist.md +37 -0
- package/core/tasks/explain-story-from-jira.md +44 -0
- package/core/tasks/facilitate-brainstorming-session.md +69 -0
- package/core/tasks/figma-audit-design-system.md +20 -0
- package/core/tasks/front-end-spec-from-design.md +33 -0
- package/core/tasks/gate.md +64 -0
- package/core/tasks/groom-jira-story.md +52 -0
- package/core/tasks/help.md +27 -0
- package/core/tasks/implement-freeform-work-item.md +30 -0
- package/core/tasks/implement-story-from-jira.md +63 -0
- package/core/tasks/implement-unit-tests.md +45 -0
- package/core/tasks/market-research-from-context7.md +37 -0
- package/core/tasks/review-story.md +30 -0
- package/core/tasks/sonarqube-hotspot-review.md +39 -0
- package/core/tasks/standup-digest.md +21 -0
- package/core/tasks/sync-jira-backlog.md +32 -0
- package/core/tasks/test-design.md +68 -0
- package/core/tasks/validate-next-story.md +37 -0
- package/core/tasks/verify-jira-story-e2e.md +45 -0
- package/core/templates/architecture-tmpl.yaml +651 -0
- package/core/templates/brainstorming-output-tmpl.yaml +156 -0
- package/core/templates/brownfield-architecture-tmpl.yaml +477 -0
- package/core/templates/brownfield-prd-tmpl.yaml +281 -0
- package/core/templates/front-end-architecture-tmpl.yaml +219 -0
- package/core/templates/front-end-spec-tmpl.yaml +350 -0
- package/core/templates/fullstack-architecture-tmpl.yaml +824 -0
- package/core/templates/market-research-tmpl.yaml +253 -0
- package/core/templates/prd-tmpl.yaml +203 -0
- package/core/templates/project-brief-tmpl.yaml +222 -0
- package/core/templates/qa-gate-tmpl.yaml +103 -0
- package/core/templates/story-tmpl.yaml +138 -0
- package/core/workflows/brownfield-fullstack.yaml +298 -0
- package/core/workflows/brownfield-service.yaml +188 -0
- package/core/workflows/brownfield-ui.yaml +198 -0
- package/core/workflows/greenfield-fullstack.yaml +241 -0
- package/core/workflows/greenfield-service.yaml +207 -0
- package/core/workflows/greenfield-ui.yaml +236 -0
- package/dist/agents/aigile-master.txt +500 -0
- package/dist/agents/aigile-orchestrator.agent.txt +224 -0
- package/dist/agents/analyst.txt +69 -0
- package/dist/agents/architect.txt +67 -0
- package/dist/agents/code-tour.agent.txt +232 -0
- package/dist/agents/dev.agent.txt +169 -0
- package/dist/agents/dev.txt +154 -0
- package/dist/agents/expert-react-frontend-engineer.agent.txt +765 -0
- package/dist/agents/pm.txt +57 -0
- package/dist/agents/po.txt +59 -0
- package/dist/agents/qa.txt +62 -0
- package/dist/agents/sm.txt +55 -0
- package/dist/agents/ui-expert.txt +63 -0
- package/dist/agents/ux-expert.txt +55 -0
- package/dist/dev-agent-bundle.txt +154 -0
- package/dist/teams/team-company.txt +10789 -0
- package/docs/mcp-servers.md +102 -0
- package/docs/orchestrator-guide.md +526 -0
- package/mcp/servers.json +108 -0
- package/mcp/servers.yaml +124 -0
- package/package.json +72 -0
- package/tools/cli.js +1864 -0
- package/tools/installer/README.md +24 -0
- package/tools/installer/lib/ide-setup.js +295 -0
- package/tools/installer/lib/installer.js +131 -0
- package/tools/md-assets/web-agent-startup-instructions.md +21 -0
- package/tools/postinstall.js +72 -0
- package/tools/shared/bannerArt.js +68 -0
- package/tools/validate-bundles.js +54 -0
- package/tools/verify-publish-registry.js +34 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# AIgile Installer (GitHub Copilot Only)
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
|
|
5
|
+
- Interactive (via your existing CLI):
|
|
6
|
+
- `npx aigile-method install`
|
|
7
|
+
- `npm run install:aigile`
|
|
8
|
+
- Add MCP templates: `npx aigile-method install --with-mcp`
|
|
9
|
+
- Add mock VS Code MCP settings: `npx aigile-method install --with-mcp-settings`
|
|
10
|
+
- Interactive prompts will ask about MCP options; use `--yes` to accept defaults quickly
|
|
11
|
+
|
|
12
|
+
What it does:
|
|
13
|
+
- Copies `core/` into `.aigile-core/` in your current project
|
|
14
|
+
- Generates GitHub Copilot chat modes from your agents into `.github/chatmodes/*.chatmode.md`
|
|
15
|
+
- Leaves your repo otherwise untouched
|
|
16
|
+
- Prints a friendly ASCII banner during installation
|
|
17
|
+
- Optional: generates `.vscode/mcp.json` with template servers and input prompts
|
|
18
|
+
- Optional: updates `.vscode/settings.json` with mock MCP endpoints (for demos)
|
|
19
|
+
- Shows a small “Created by GM” banner and a short summary on completion
|
|
20
|
+
|
|
21
|
+
Notes:
|
|
22
|
+
- This installer is intentionally scoped to GitHub Copilot compatibility.
|
|
23
|
+
- MCP/other IDEs can be added later as separate options.
|
|
24
|
+
- After generating `.vscode/mcp.json`, open VS Code and fill in the prompted API keys.
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Full tool list for all agents (except orchestrator)
|
|
6
|
+
*/
|
|
7
|
+
const FULL_AGENT_TOOLS = [
|
|
8
|
+
// VS Code tools
|
|
9
|
+
'vscode/getProjectSetupInfo', 'vscode/installExtension', 'vscode/newWorkspace',
|
|
10
|
+
'vscode/openSimpleBrowser', 'vscode/runCommand', 'vscode/vscodeAPI', 'vscode/extensions',
|
|
11
|
+
// Execute tools
|
|
12
|
+
'execute/runNotebookCell', 'execute/testFailure', 'execute/getTerminalOutput',
|
|
13
|
+
'execute/runTask', 'execute/createAndRunTask', 'execute/runInTerminal', 'execute/runTests',
|
|
14
|
+
// Read tools
|
|
15
|
+
'read/getNotebookSummary', 'read/problems', 'read/readFile', 'read/readNotebookCellOutput',
|
|
16
|
+
'read/terminalSelection', 'read/terminalLastCommand', 'read/getTaskOutput',
|
|
17
|
+
// Agent tools
|
|
18
|
+
'agent/runSubagent',
|
|
19
|
+
// Edit tools
|
|
20
|
+
'edit/createDirectory', 'edit/createFile', 'edit/createJupyterNotebook',
|
|
21
|
+
'edit/editFiles', 'edit/editNotebook',
|
|
22
|
+
// Search tools
|
|
23
|
+
'search/changes', 'search/codebase', 'search/fileSearch', 'search/listDirectory',
|
|
24
|
+
'search/searchResults', 'search/textSearch', 'search/usages', 'search/searchSubagent',
|
|
25
|
+
// Web tools
|
|
26
|
+
'web/fetch', 'web/githubRepo',
|
|
27
|
+
// Context7 MCP
|
|
28
|
+
'upstash/context7/query-docs', 'upstash/context7/resolve-library-id',
|
|
29
|
+
// GitHub MCP
|
|
30
|
+
'github/add_comment_to_pending_review', 'github/add_issue_comment', 'github/assign_copilot_to_issue',
|
|
31
|
+
'github/create_branch', 'github/create_or_update_file', 'github/create_pull_request',
|
|
32
|
+
'github/create_repository', 'github/delete_file', 'github/fork_repository', 'github/get_commit',
|
|
33
|
+
'github/get_file_contents', 'github/get_label', 'github/get_latest_release', 'github/get_me',
|
|
34
|
+
'github/get_release_by_tag', 'github/get_tag', 'github/get_team_members', 'github/get_teams',
|
|
35
|
+
'github/issue_read', 'github/issue_write', 'github/list_branches', 'github/list_commits',
|
|
36
|
+
'github/list_issue_types', 'github/list_issues', 'github/list_pull_requests', 'github/list_releases',
|
|
37
|
+
'github/list_tags', 'github/merge_pull_request', 'github/pull_request_read',
|
|
38
|
+
'github/pull_request_review_write', 'github/push_files', 'github/request_copilot_review',
|
|
39
|
+
'github/search_code', 'github/search_issues', 'github/search_pull_requests',
|
|
40
|
+
'github/search_repositories', 'github/search_users', 'github/sub_issue_write',
|
|
41
|
+
'github/update_pull_request', 'github/update_pull_request_branch',
|
|
42
|
+
// Other tools
|
|
43
|
+
'askQuestions', 'todo',
|
|
44
|
+
// GitHub PR extension tools
|
|
45
|
+
'github.vscode-pull-request-github/issue_fetch', 'github.vscode-pull-request-github/suggest-fix',
|
|
46
|
+
'github.vscode-pull-request-github/searchSyntax', 'github.vscode-pull-request-github/doSearch',
|
|
47
|
+
'github.vscode-pull-request-github/renderIssues', 'github.vscode-pull-request-github/activePullRequest',
|
|
48
|
+
'github.vscode-pull-request-github/openPullRequest'
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Agent metadata extracted from legacy YAML blocks
|
|
53
|
+
*/
|
|
54
|
+
const AGENT_METADATA = {
|
|
55
|
+
'aigile-orchestrator': {
|
|
56
|
+
description: 'PURE COORDINATOR - I have NO implementation tools. I can ONLY delegate via runSubagent.',
|
|
57
|
+
tools: ['agent/runSubagent'],
|
|
58
|
+
model: 'Claude Opus 4.5',
|
|
59
|
+
handoffs: [
|
|
60
|
+
{ label: '🏗️ Architecture Review', agent: 'architect', prompt: 'Analyze the architecture and provide recommendations.', send: false },
|
|
61
|
+
{ label: '💻 Start Implementation', agent: 'dev', prompt: 'Implement the plan using test-driven development.', send: false },
|
|
62
|
+
{ label: '🧪 Run QA Gate', agent: 'qa', prompt: 'Review and test the implementation for quality.', send: false },
|
|
63
|
+
{ label: '📋 Refine Backlog', agent: 'po', prompt: 'Refine the backlog items based on discussion.', send: false },
|
|
64
|
+
{ label: '🧠 Analyze Requirements', agent: 'analyst', prompt: 'Analyze requirements and provide breakdown.', send: false },
|
|
65
|
+
],
|
|
66
|
+
infer: false
|
|
67
|
+
},
|
|
68
|
+
'dev': {
|
|
69
|
+
description: 'Full Stack Developer - code implementation, debugging, refactoring, and test-driven development.',
|
|
70
|
+
tools: FULL_AGENT_TOOLS,
|
|
71
|
+
model: 'Claude Opus 4.5',
|
|
72
|
+
handoffs: [
|
|
73
|
+
{ label: '🧪 Request QA Review', agent: 'qa', prompt: 'Review the implementation above for quality.', send: false },
|
|
74
|
+
{ label: '🏗️ Architecture Check', agent: 'architect', prompt: 'Verify architecture compliance.', send: false },
|
|
75
|
+
],
|
|
76
|
+
infer: true
|
|
77
|
+
},
|
|
78
|
+
'architect': {
|
|
79
|
+
description: 'Software Architect - architecture analysis, code review, documentation, and system design.',
|
|
80
|
+
tools: FULL_AGENT_TOOLS,
|
|
81
|
+
model: 'Claude Opus 4.5',
|
|
82
|
+
handoffs: [
|
|
83
|
+
{ label: '💻 Start Implementation', agent: 'dev', prompt: 'Implement the architecture recommendations.', send: false },
|
|
84
|
+
{ label: '📋 Create Stories', agent: 'po', prompt: 'Create backlog items for architecture changes.', send: false },
|
|
85
|
+
],
|
|
86
|
+
infer: true
|
|
87
|
+
},
|
|
88
|
+
'po': {
|
|
89
|
+
description: 'Product Owner - story creation, backlog management, and Jira integration.',
|
|
90
|
+
tools: FULL_AGENT_TOOLS,
|
|
91
|
+
model: 'Claude Opus 4.5',
|
|
92
|
+
handoffs: [
|
|
93
|
+
{ label: '💻 Implement Story', agent: 'dev', prompt: 'Implement the story defined above.', send: false },
|
|
94
|
+
{ label: '🧠 Analyze Further', agent: 'analyst', prompt: 'Provide deeper analysis of requirements.', send: false },
|
|
95
|
+
],
|
|
96
|
+
infer: true
|
|
97
|
+
},
|
|
98
|
+
'qa': {
|
|
99
|
+
description: 'QA Engineer - testing, quality gates, E2E verification, and test automation.',
|
|
100
|
+
tools: FULL_AGENT_TOOLS,
|
|
101
|
+
model: 'Claude Opus 4.5',
|
|
102
|
+
handoffs: [
|
|
103
|
+
{ label: '💻 Fix Issues', agent: 'dev', prompt: 'Fix the issues identified in QA review.', send: false },
|
|
104
|
+
{ label: '📋 Update Stories', agent: 'po', prompt: 'Update stories based on QA findings.', send: false },
|
|
105
|
+
],
|
|
106
|
+
infer: true
|
|
107
|
+
},
|
|
108
|
+
'analyst': {
|
|
109
|
+
description: 'Business Analyst - requirements analysis, brainstorming, research, and elicitation.',
|
|
110
|
+
tools: FULL_AGENT_TOOLS,
|
|
111
|
+
model: 'Claude Opus 4.5',
|
|
112
|
+
handoffs: [
|
|
113
|
+
{ label: '📋 Create Stories', agent: 'po', prompt: 'Create stories from analysis findings.', send: false },
|
|
114
|
+
{ label: '🏗️ Architecture Review', agent: 'architect', prompt: 'Review architecture implications.', send: false },
|
|
115
|
+
],
|
|
116
|
+
infer: true
|
|
117
|
+
},
|
|
118
|
+
'pm': {
|
|
119
|
+
description: 'Project Manager - project planning, backlog sync, PRDs, and roadmap management.',
|
|
120
|
+
tools: FULL_AGENT_TOOLS,
|
|
121
|
+
model: 'Claude Opus 4.5',
|
|
122
|
+
handoffs: [
|
|
123
|
+
{ label: '📋 Refine Stories', agent: 'po', prompt: 'Refine the stories in the plan.', send: false },
|
|
124
|
+
],
|
|
125
|
+
infer: true
|
|
126
|
+
},
|
|
127
|
+
'sm': {
|
|
128
|
+
description: 'Scrum Master - sprint ceremonies, standup facilitation, and team coordination.',
|
|
129
|
+
tools: FULL_AGENT_TOOLS,
|
|
130
|
+
model: 'Claude Opus 4.5',
|
|
131
|
+
handoffs: [],
|
|
132
|
+
infer: true
|
|
133
|
+
},
|
|
134
|
+
'ui-expert': {
|
|
135
|
+
description: 'UI Expert - design system audit, Figma integration, and component specifications.',
|
|
136
|
+
tools: FULL_AGENT_TOOLS,
|
|
137
|
+
model: 'Claude Opus 4.5',
|
|
138
|
+
handoffs: [
|
|
139
|
+
{ label: '💻 Implement UI', agent: 'dev', prompt: 'Implement the UI specifications.', send: false },
|
|
140
|
+
],
|
|
141
|
+
infer: true
|
|
142
|
+
},
|
|
143
|
+
'ux-expert': {
|
|
144
|
+
description: 'UX Expert - user experience design, frontend specs, and user journey mapping.',
|
|
145
|
+
tools: FULL_AGENT_TOOLS,
|
|
146
|
+
model: 'Claude Opus 4.5',
|
|
147
|
+
handoffs: [
|
|
148
|
+
{ label: '🖌️ Design System', agent: 'ui-expert', prompt: 'Create design system components.', send: false },
|
|
149
|
+
{ label: '💻 Implement UX', agent: 'dev', prompt: 'Implement the UX recommendations.', send: false },
|
|
150
|
+
],
|
|
151
|
+
infer: true
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Extract agent ID from filename
|
|
157
|
+
*/
|
|
158
|
+
function getAgentId(filename) {
|
|
159
|
+
return filename
|
|
160
|
+
.replace(/\.agent\.md$/, '')
|
|
161
|
+
.replace(/\.md$/, '');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Check if file is already in new agent format
|
|
166
|
+
*/
|
|
167
|
+
function isNewAgentFormat(filename) {
|
|
168
|
+
return filename.endsWith('.agent.md');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Generate YAML frontmatter for custom agent
|
|
173
|
+
*/
|
|
174
|
+
function generateFrontmatter(id, metadata) {
|
|
175
|
+
const lines = ['---'];
|
|
176
|
+
|
|
177
|
+
if (metadata.name) lines.push(`name: ${metadata.name}`);
|
|
178
|
+
lines.push(`description: "${metadata.description || `Activates the ${id} agent persona (AIgile).`}"`);
|
|
179
|
+
if (metadata.argumentHint) lines.push(`argument-hint: "${metadata.argumentHint}"`);
|
|
180
|
+
|
|
181
|
+
if (metadata.tools && metadata.tools.length > 0) {
|
|
182
|
+
lines.push('tools:');
|
|
183
|
+
for (const tool of metadata.tools) {
|
|
184
|
+
lines.push(` - ${tool}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Always add model - default to Claude Opus 4.5
|
|
189
|
+
lines.push(`model: ${metadata.model || 'Claude Opus 4.5'}`);
|
|
190
|
+
if (metadata.infer !== undefined) lines.push(`infer: ${metadata.infer}`);
|
|
191
|
+
|
|
192
|
+
if (metadata.handoffs && metadata.handoffs.length > 0) {
|
|
193
|
+
lines.push('handoffs:');
|
|
194
|
+
for (const handoff of metadata.handoffs) {
|
|
195
|
+
lines.push(` - label: "${handoff.label}"`);
|
|
196
|
+
lines.push(` agent: ${handoff.agent}`);
|
|
197
|
+
lines.push(` prompt: "${handoff.prompt}"`);
|
|
198
|
+
lines.push(` send: ${handoff.send}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
lines.push('---');
|
|
203
|
+
return lines.join('\n');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Setup GitHub Copilot custom agents (new format)
|
|
208
|
+
* Creates .agent.md files in .github/agents/ folder
|
|
209
|
+
*
|
|
210
|
+
* @deprecated destChatmodesDir parameter - now creates agents in .github/agents/
|
|
211
|
+
*/
|
|
212
|
+
export function setupGithubCopilot({ srcAgentsDir, destChatmodesDir, destAgentsDir }){
|
|
213
|
+
// Use new agents directory, fallback to chatmodes for backward compatibility
|
|
214
|
+
const targetDir = destAgentsDir || destChatmodesDir?.replace('chatmodes', 'agents') || destChatmodesDir;
|
|
215
|
+
|
|
216
|
+
fs.mkdirpSync(targetDir);
|
|
217
|
+
if(!srcAgentsDir || !fs.existsSync(srcAgentsDir)) return;
|
|
218
|
+
|
|
219
|
+
const processedAgents = [];
|
|
220
|
+
|
|
221
|
+
for(const name of fs.readdirSync(srcAgentsDir)){
|
|
222
|
+
if(!name.endsWith('.md')) continue;
|
|
223
|
+
|
|
224
|
+
const id = getAgentId(name);
|
|
225
|
+
const srcPath = path.join(srcAgentsDir, name);
|
|
226
|
+
const agentMd = fs.readFileSync(srcPath, 'utf8');
|
|
227
|
+
|
|
228
|
+
// If already in new .agent.md format, copy directly
|
|
229
|
+
if (isNewAgentFormat(name)) {
|
|
230
|
+
fs.copyFileSync(srcPath, path.join(targetDir, name));
|
|
231
|
+
processedAgents.push({ id, format: 'native' });
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Convert legacy format to new custom agent format
|
|
236
|
+
const metadata = AGENT_METADATA[id] || {
|
|
237
|
+
description: `Activates the ${id} agent persona (AIgile).`,
|
|
238
|
+
tools: ['search', 'fetch', 'codebase', 'problems'],
|
|
239
|
+
handoffs: [],
|
|
240
|
+
infer: true
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const frontmatter = generateFrontmatter(id, metadata);
|
|
244
|
+
|
|
245
|
+
// Transform the content - remove old activation notice if present
|
|
246
|
+
let content = agentMd;
|
|
247
|
+
|
|
248
|
+
// Add activation context header
|
|
249
|
+
const header = [
|
|
250
|
+
'',
|
|
251
|
+
'# Activation Notice',
|
|
252
|
+
'',
|
|
253
|
+
'This agent is part of the AIgile framework. The instructions below define your operating guidelines.',
|
|
254
|
+
'Use `#tool:runSubagent` to delegate specialized tasks to other agents when appropriate.',
|
|
255
|
+
'',
|
|
256
|
+
].join('\n');
|
|
257
|
+
|
|
258
|
+
const out = `${frontmatter}${header}${content}`;
|
|
259
|
+
const destFile = path.join(targetDir, `${id}.agent.md`);
|
|
260
|
+
fs.writeFileSync(destFile, out, 'utf8');
|
|
261
|
+
processedAgents.push({ id, format: 'converted' });
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return processedAgents;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Setup legacy chatmodes (deprecated - for backward compatibility)
|
|
269
|
+
* @deprecated Use setupGithubCopilot with destAgentsDir instead
|
|
270
|
+
*/
|
|
271
|
+
export function setupLegacyChatmodes({ srcAgentsDir, destChatmodesDir }){
|
|
272
|
+
console.warn('Warning: chatmodes are deprecated. Use custom agents (.github/agents/) instead.');
|
|
273
|
+
fs.mkdirpSync(destChatmodesDir);
|
|
274
|
+
if(!srcAgentsDir || !fs.existsSync(srcAgentsDir)) return;
|
|
275
|
+
|
|
276
|
+
for(const name of fs.readdirSync(srcAgentsDir)){
|
|
277
|
+
if(!name.endsWith('.md')) continue;
|
|
278
|
+
const id = getAgentId(name);
|
|
279
|
+
const agentMd = fs.readFileSync(path.join(srcAgentsDir, name), 'utf8');
|
|
280
|
+
|
|
281
|
+
const header = [
|
|
282
|
+
'---',
|
|
283
|
+
`description: "Activates the ${id} agent persona (AIgile)."`,
|
|
284
|
+
'---',
|
|
285
|
+
'',
|
|
286
|
+
'# Activation Notice',
|
|
287
|
+
'This file contains the full agent operating guidelines for GitHub Copilot Chat.',
|
|
288
|
+
'Follow the YAML inside to assume this role and operate within these constraints.',
|
|
289
|
+
'',
|
|
290
|
+
].join('\n');
|
|
291
|
+
|
|
292
|
+
const out = `${header}${agentMd}`;
|
|
293
|
+
fs.writeFileSync(path.join(destChatmodesDir, `${id}.chatmode.md`), out, 'utf8');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { setupGithubCopilot, setupLegacyChatmodes } from './ide-setup.js';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const projectRoot = path.resolve(__dirname, '..', '..');
|
|
9
|
+
|
|
10
|
+
function copyDir(src, dest){
|
|
11
|
+
if(!fs.existsSync(src)) return;
|
|
12
|
+
fs.mkdirpSync(dest);
|
|
13
|
+
for(const entry of fs.readdirSync(src, {withFileTypes:true})){
|
|
14
|
+
const sp = path.join(src, entry.name);
|
|
15
|
+
const dp = path.join(dest, entry.name);
|
|
16
|
+
if(entry.isDirectory()) copyDir(sp, dp);
|
|
17
|
+
else fs.copyFileSync(sp, dp);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// legacy helper kept for compatibility; now defers to setupGithubCopilot
|
|
22
|
+
function makeChatModesFromAgents(srcAgentsDir, destChatmodesDir){
|
|
23
|
+
setupGithubCopilot({ srcAgentsDir, destChatmodesDir });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function runInstall({ withMcp=false, includeJavaInstructions=false, useLegacyChatmodes=false } = {}){
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
|
|
29
|
+
// 1) Copy core -> .aigile-core
|
|
30
|
+
const coreSrc = path.join(projectRoot, 'core');
|
|
31
|
+
const coreDest = path.join(cwd, '.aigile-core');
|
|
32
|
+
copyDir(coreSrc, coreDest);
|
|
33
|
+
|
|
34
|
+
// 2) Generate GitHub Copilot custom agents (new format: .github/agents/*.agent.md)
|
|
35
|
+
// Or legacy chatmodes if explicitly requested
|
|
36
|
+
const srcAgentsDir = path.join(coreSrc, 'agents');
|
|
37
|
+
let outputDir;
|
|
38
|
+
|
|
39
|
+
if (useLegacyChatmodes) {
|
|
40
|
+
// Deprecated: Use legacy chatmodes format
|
|
41
|
+
outputDir = path.join(cwd, '.github', 'chatmodes');
|
|
42
|
+
setupLegacyChatmodes({ srcAgentsDir, destChatmodesDir: outputDir });
|
|
43
|
+
console.log('⚠️ Warning: Using legacy chatmodes format. Consider upgrading to custom agents.');
|
|
44
|
+
} else {
|
|
45
|
+
// New format: Custom agents with handoffs and runSubagent support
|
|
46
|
+
outputDir = path.join(cwd, '.github', 'agents');
|
|
47
|
+
const agents = setupGithubCopilot({ srcAgentsDir, destAgentsDir: outputDir });
|
|
48
|
+
console.log(`✅ Created ${agents?.length || 0} custom agents in .github/agents/`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 3) Create copilot-instructions.md for workspace-wide settings
|
|
52
|
+
const instructionsDir = path.join(cwd, '.github');
|
|
53
|
+
fs.mkdirpSync(instructionsDir);
|
|
54
|
+
const copilotInstructionsPath = path.join(instructionsDir, 'copilot-instructions.md');
|
|
55
|
+
if (!fs.existsSync(copilotInstructionsPath)) {
|
|
56
|
+
const copilotInstructions = `# AIgile Copilot Instructions
|
|
57
|
+
|
|
58
|
+
This project uses the AIgile framework for AI-assisted development.
|
|
59
|
+
|
|
60
|
+
## Custom Agents
|
|
61
|
+
|
|
62
|
+
Custom agents are available in \`.github/agents/\`. Use them by selecting from the agent dropdown in Copilot Chat.
|
|
63
|
+
|
|
64
|
+
### Available Agents
|
|
65
|
+
- **aigile-orchestrator**: Master orchestrator - coordinates workflows and delegates to specialists
|
|
66
|
+
- **dev**: Full Stack Developer - implementation, debugging, TDD
|
|
67
|
+
- **architect**: Software Architect - architecture review, documentation
|
|
68
|
+
- **po**: Product Owner - story creation, backlog management
|
|
69
|
+
- **qa**: QA Engineer - testing, quality gates
|
|
70
|
+
- **analyst**: Business Analyst - requirements analysis
|
|
71
|
+
- **pm**: Project Manager - project planning
|
|
72
|
+
- **sm**: Scrum Master - ceremonies, team coordination
|
|
73
|
+
- **ui-expert**: UI Expert - design systems, Figma
|
|
74
|
+
- **ux-expert**: UX Expert - user experience design
|
|
75
|
+
|
|
76
|
+
## Subagent Delegation
|
|
77
|
+
|
|
78
|
+
The orchestrator and specialist agents can delegate tasks using \`#tool:runSubagent\`.
|
|
79
|
+
This enables autonomous multi-step workflows where complex tasks are broken down
|
|
80
|
+
and routed to the appropriate specialist.
|
|
81
|
+
|
|
82
|
+
## Handoffs
|
|
83
|
+
|
|
84
|
+
Agents support handoffs - use the handoff buttons after a response to transition
|
|
85
|
+
to another specialist with context preserved.
|
|
86
|
+
|
|
87
|
+
## Project Configuration
|
|
88
|
+
|
|
89
|
+
See \`.aigile-core/core-config.yaml\` for project-specific settings.
|
|
90
|
+
`;
|
|
91
|
+
fs.writeFileSync(copilotInstructionsPath, copilotInstructions, 'utf8');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 4) Optional MCP scaffolding into .vscode (disabled by default for Copilot-only)
|
|
95
|
+
if(withMcp){
|
|
96
|
+
const vsSettingsDir = path.join(cwd, '.vscode');
|
|
97
|
+
fs.mkdirpSync(vsSettingsDir);
|
|
98
|
+
const settingsPath = path.join(vsSettingsDir, 'settings.json');
|
|
99
|
+
if(!fs.existsSync(settingsPath)){
|
|
100
|
+
fs.writeFileSync(settingsPath, JSON.stringify({
|
|
101
|
+
"aigile.mcp": { enabled: true },
|
|
102
|
+
"github.copilot.chat.customAgents.showOrganizationAndEnterpriseAgents": true
|
|
103
|
+
}, null, 2));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if(includeJavaInstructions){
|
|
108
|
+
const javaInstructionsSrc = path.join(projectRoot, 'core', 'instructions', 'java.instructions.md');
|
|
109
|
+
if(fs.existsSync(javaInstructionsSrc)){
|
|
110
|
+
const instructionsDest = path.join(cwd, '.github', 'instructions');
|
|
111
|
+
fs.mkdirpSync(instructionsDest);
|
|
112
|
+
fs.copyFileSync(javaInstructionsSrc, path.join(instructionsDest, 'java.instructions.md'));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Marker file with version info
|
|
117
|
+
const markerContent = JSON.stringify({
|
|
118
|
+
version: '0.3.0',
|
|
119
|
+
format: useLegacyChatmodes ? 'chatmodes' : 'agents',
|
|
120
|
+
installedAt: new Date().toISOString(),
|
|
121
|
+
features: {
|
|
122
|
+
customAgents: !useLegacyChatmodes,
|
|
123
|
+
handoffs: !useLegacyChatmodes,
|
|
124
|
+
runSubagent: !useLegacyChatmodes,
|
|
125
|
+
mcp: withMcp
|
|
126
|
+
}
|
|
127
|
+
}, null, 2);
|
|
128
|
+
fs.writeFileSync(path.join(cwd, '.aigile'), markerContent, 'utf8');
|
|
129
|
+
|
|
130
|
+
return { coreDest, agentsDir: outputDir, chatmodesDir: useLegacyChatmodes ? outputDir : null };
|
|
131
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Web Agent Bundle Instructions
|
|
2
|
+
|
|
3
|
+
This header is included at the top of each generated AIgile bundle (team and per-agent) to provide context for downstream tooling and validation.
|
|
4
|
+
|
|
5
|
+
Purpose:
|
|
6
|
+
- Identify the file as a structured AIgile bundle
|
|
7
|
+
- Provide quick usage guidance
|
|
8
|
+
- Ensure automated validators can assert presence (looks for the phrase: Web Agent Bundle Instructions)
|
|
9
|
+
|
|
10
|
+
Usage Guidance:
|
|
11
|
+
1. Each subsequent section is wrapped with START/END markers of the form:
|
|
12
|
+
==================== START: .aigile-core/<relative-path> ====================
|
|
13
|
+
(content)
|
|
14
|
+
==================== END: .aigile-core/<relative-path> ====================
|
|
15
|
+
2. Tools parsing this file should iterate over marker pairs to reconstruct original source files under `.aigile-core/`.
|
|
16
|
+
3. Do not edit marker lines manually—regenerate bundles instead (`npm run build`).
|
|
17
|
+
4. Additional metadata or future headers can be appended below this notice.
|
|
18
|
+
|
|
19
|
+
Notes:
|
|
20
|
+
- Missing this header triggers validation failure.
|
|
21
|
+
- Keep this concise; large instructions inflate bundle size.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Postinstall bootstrap for @mark-gozner/aigile-method
|
|
4
|
+
*
|
|
5
|
+
* Goal: Allow a single command install:
|
|
6
|
+
* npm install @mark-gozner/aigile-method
|
|
7
|
+
* which automatically lays down .aigile-core and agents in the *consuming* project.
|
|
8
|
+
*
|
|
9
|
+
* Safeguards / Opt-outs:
|
|
10
|
+
* - Set AIGILE_NO_POSTINSTALL=1 to skip entirely
|
|
11
|
+
* - Set CI=true (common in pipelines) to skip (avoid polluting build images)
|
|
12
|
+
* - Set AIGILE_INSTALL_ARGS="--with-mcp" to pass extra flags
|
|
13
|
+
* - Set AIGILE_SILENT=1 to suppress non-error logging
|
|
14
|
+
*
|
|
15
|
+
* Behavior:
|
|
16
|
+
* 1. Detect if running inside the package itself (development) -> if so, skip
|
|
17
|
+
* 2. Otherwise invoke tools/cli.js install with optional flags
|
|
18
|
+
*/
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
|
|
24
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
25
|
+
const __dirname = path.dirname(__filename);
|
|
26
|
+
const pkgRoot = path.resolve(__dirname, '..');
|
|
27
|
+
|
|
28
|
+
function log(msg){ if(!process.env.AIGILE_SILENT) console.log(`[aigile-postinstall] ${msg}`); }
|
|
29
|
+
function warn(msg){ console.warn(`[aigile-postinstall] WARN: ${msg}`); }
|
|
30
|
+
function skip(reason){ log(`Skipped automatic install: ${reason}`); process.exit(0); }
|
|
31
|
+
|
|
32
|
+
// 1. Global skips
|
|
33
|
+
if(process.env.AIGILE_NO_POSTINSTALL === '1') skip('AIGILE_NO_POSTINSTALL=1');
|
|
34
|
+
if(process.env.CI === 'true') skip('CI=true');
|
|
35
|
+
|
|
36
|
+
// 2. Detect if we're inside the package's own repo (development scenario)
|
|
37
|
+
// Heuristic: presence of .git AND core/agents folder at same root as this script.
|
|
38
|
+
const devIndicators = [
|
|
39
|
+
path.join(pkgRoot, '.git'),
|
|
40
|
+
path.join(pkgRoot, 'core', 'agents')
|
|
41
|
+
];
|
|
42
|
+
const looksLikeDev = devIndicators.every(p => fs.existsSync(p));
|
|
43
|
+
if(looksLikeDev) skip('development workspace detected');
|
|
44
|
+
|
|
45
|
+
// 3. Determine project root (one level above node_modules/<this package>)
|
|
46
|
+
// process.cwd() during postinstall is the consuming project root for npm (unless workspaces alter it)
|
|
47
|
+
const projectRoot = process.cwd();
|
|
48
|
+
if(projectRoot.startsWith(pkgRoot)) {
|
|
49
|
+
// Unusual but guard anyway
|
|
50
|
+
skip('ambiguous install path (project root equals package root)');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 4. Build args
|
|
54
|
+
const extra = process.env.AIGILE_INSTALL_ARGS ? process.env.AIGILE_INSTALL_ARGS.split(/\s+/).filter(Boolean) : [];
|
|
55
|
+
const cliPath = path.join(pkgRoot, 'tools', 'cli.js');
|
|
56
|
+
// Use 'install' command with --yes for non-interactive install
|
|
57
|
+
const args = [cliPath, 'install', '--yes'];
|
|
58
|
+
args.push(...extra);
|
|
59
|
+
|
|
60
|
+
log(`Running automatic install into consumer project: ${projectRoot}`);
|
|
61
|
+
log(`Command: node ${args.map(a => (a.includes(' ') ? '"'+a+'"' : a)).join(' ')}`);
|
|
62
|
+
|
|
63
|
+
const child = spawn(process.execPath, args, {
|
|
64
|
+
cwd: projectRoot,
|
|
65
|
+
stdio: 'inherit',
|
|
66
|
+
env: process.env
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
child.on('exit', (code) => {
|
|
70
|
+
if(code === 0) log('AIgile installed successfully (postinstall).');
|
|
71
|
+
else warn(`AIgile postinstall exited with code ${code}. You can rerun: npx @mark-gozner/aigile-method install`);
|
|
72
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Simple ASCII banners for AIgile installer output (ESM)
|
|
2
|
+
|
|
3
|
+
export const AIGILE_TITLE = 'AIgile-Method';
|
|
4
|
+
export const INSTALLER_TITLE = 'INSTALLER';
|
|
5
|
+
|
|
6
|
+
export const AIGILE_LARGE = `
|
|
7
|
+
█████╗ ██╗ ██████╗ ██╗██╗ ███████╗ ██╗███╗ ██╗███████╗████████╗ █████╗ ██╗ ██╗ ███████╗██████╗
|
|
8
|
+
██╔══██╗██║██╔════╝ ██║██║ ██╔════╝ ██║████╗ ██║██╔════╝╚══██╔══╝██╔══██╗██║ ██║ ██╔════╝██╔══██╗
|
|
9
|
+
███████║██║██║ ███╗██║██║ █████╗ ██║██╔██╗ ██║███████╗ ██║ ███████║██║ ██║ █████╗ ██████╔╝
|
|
10
|
+
██╔══██║██║██║ ██║██║██║ ██╔══╝ ██║██║╚██╗██║╚════██║ ██║ ██╔══██║██║ ██║ ██╔══╝ ██╔══██╗
|
|
11
|
+
██║ ██║██║╚██████╔╝██║███████╗███████╗ ██║██║ ╚████║███████║ ██║ ██║ ██║███████╗███████╗███████╗██║ ██║
|
|
12
|
+
╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝╚══════╝╚══════╝ ╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝
|
|
13
|
+
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
export const INSTALLER_SMALL = `
|
|
17
|
+
╭──────────────────────────╮
|
|
18
|
+
│ AIgile Installer │
|
|
19
|
+
╰──────────────────────────╯
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
// GM signature banners
|
|
23
|
+
export const GM_LARGE = `
|
|
24
|
+
██████╗██████╗ ███████╗ █████╗ ████████╗███████╗██████╗ ██████╗ ██╗ ██╗ ██████╗ ███╗ ███╗
|
|
25
|
+
██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██╔════╝██╔══██╗ ██╔══██╗╚██╗ ██╔╝ ██╔════╝ ████╗ ████║
|
|
26
|
+
██║ ██████╔╝█████╗ ███████║ ██║ █████╗ ██║ ██║ ██████╔╝ ╚████╔╝ ██║ ███╗██╔████╔██║
|
|
27
|
+
██║ ██╔══██╗██╔══╝ ██╔══██║ ██║ ██╔══╝ ██║ ██║ ██╔══██╗ ╚██╔╝ ██║ ██║██║╚██╔╝██║
|
|
28
|
+
╚██████╗██║ ██║███████╗██║ ██║ ██║ ███████╗██████╔╝ ██████╔╝ ██║ ╚██████╔╝██║ ╚═╝ ██║
|
|
29
|
+
╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
|
|
30
|
+
|
|
31
|
+
`;
|
|
32
|
+
export const GM_MEDIUM = `
|
|
33
|
+
╭──────────────────────────╮
|
|
34
|
+
│ Created by GM │
|
|
35
|
+
╰──────────────────────────╯
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
function applyGradient(text, startColor, endColor) {
|
|
39
|
+
const length = text.length;
|
|
40
|
+
let result = '';
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < length; i++) {
|
|
43
|
+
const char = text[i];
|
|
44
|
+
if (char === '\n') {
|
|
45
|
+
result += char;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const ratio = i / length;
|
|
49
|
+
const r = Math.round(startColor.r + ratio * (endColor.r - startColor.r));
|
|
50
|
+
const g = Math.round(startColor.g + ratio * (endColor.g - startColor.g));
|
|
51
|
+
const b = Math.round(startColor.b + ratio * (endColor.b - startColor.b));
|
|
52
|
+
result += `\x1b[38;2;${r};${g};${b}m${char}\x1b[0m`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function printInstallBanner({ showGMSignature = true } = {}) {
|
|
59
|
+
const neonGreen = { r: 57, g: 255, b: 20 }; // Neon green
|
|
60
|
+
const cyan = { r: 0, g: 255, b: 255 }; // Cyan
|
|
61
|
+
const magenta = { r: 255, g: 0, b: 255 }; // Magenta
|
|
62
|
+
const orange = { r: 255, g: 165, b: 0 }; // Orange
|
|
63
|
+
|
|
64
|
+
console.log('\n' + applyGradient(AIGILE_LARGE, neonGreen, cyan));
|
|
65
|
+
if (showGMSignature) {
|
|
66
|
+
console.log(applyGradient(GM_LARGE, magenta, orange));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const root = path.resolve(__dirname, '..');
|
|
9
|
+
const dist = path.join(root, 'dist');
|
|
10
|
+
|
|
11
|
+
function fail(msg){
|
|
12
|
+
console.error('❌', msg);
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function ok(msg){
|
|
17
|
+
console.log('✅', msg);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function mustExist(p){
|
|
21
|
+
if(!fs.existsSync(p)) fail(`Missing: ${path.relative(root, p)}`);
|
|
22
|
+
else ok(`Exists: ${path.relative(root, p)}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function checkMarkers(file){
|
|
26
|
+
const txt = fs.readFileSync(file, 'utf8');
|
|
27
|
+
if(!txt.includes('Web Agent Bundle Instructions')) fail(`${path.basename(file)} missing header`);
|
|
28
|
+
const startCount = (txt.match(/==================== START:/g) || []).length;
|
|
29
|
+
const endCount = (txt.match(/==================== END:/g) || []).length;
|
|
30
|
+
if(startCount === 0 || endCount === 0) fail(`${path.basename(file)} missing START/END markers`);
|
|
31
|
+
if(startCount !== endCount) fail(`${path.basename(file)} START/END count mismatch (${startCount} vs ${endCount})`);
|
|
32
|
+
else ok(`${path.basename(file)} markers balanced (${startCount})`);
|
|
33
|
+
if(!txt.includes('.aigile-core/')) fail(`${path.basename(file)} missing .aigile-core paths`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function main(){
|
|
37
|
+
mustExist(dist);
|
|
38
|
+
const team = path.join(dist, 'teams', 'team-company.txt');
|
|
39
|
+
const agentsDir = path.join(dist, 'agents');
|
|
40
|
+
mustExist(team);
|
|
41
|
+
mustExist(agentsDir);
|
|
42
|
+
const dev = path.join(agentsDir, 'dev.txt');
|
|
43
|
+
if(fs.existsSync(dev)) ok('dev agent bundle present');
|
|
44
|
+
else console.warn('ℹ️ dev agent bundle not found (ok if no dev.md)');
|
|
45
|
+
checkMarkers(team);
|
|
46
|
+
if(fs.existsSync(dev)) checkMarkers(dev);
|
|
47
|
+
|
|
48
|
+
// Sanity: ensure team includes at least one agent file content by looking for core/agents/
|
|
49
|
+
const teamTxt = fs.readFileSync(team, 'utf8');
|
|
50
|
+
if(!teamTxt.includes('/agents/')) fail('team-company.txt does not seem to include any agent content');
|
|
51
|
+
else ok('team-company.txt includes agent content');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
main();
|