everything-gemini 1.2.0 → 1.9.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/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
- package/.github/ISSUE_TEMPLATE/subagent_proposal.md +29 -0
- package/.github/workflows/ci.yml +72 -1
- package/.github/workflows/release.yml +17 -2
- package/CHANGELOG.md +178 -0
- package/CONTRIBUTING.md +90 -4
- package/README.md +147 -23
- package/action.yml +35 -0
- package/agents/browser-qa.md +1 -1
- package/agents/database-migrator.md +26 -0
- package/agents/documentation-writer.md +27 -0
- package/agents/incident-responder.md +34 -0
- package/agents/performance-tuner.md +27 -0
- package/agents/platform-engineer.md +33 -0
- package/agents/release-engineer.md +34 -0
- package/bin/everything-gemini +1791 -142
- package/docs/COMMUNITY_SUBMISSIONS.md +88 -0
- package/docs/LAUNCH_KIT.md +138 -13
- package/docs/architecture/progressive-disclosure.md +3 -3
- package/docs/index.html +410 -40
- package/docs/launch-kit.md +163 -0
- package/examples/cli-workflows/demo_workflow.sh +15 -7
- package/examples/python-sdk/README.md +32 -5
- package/examples/python-sdk/documentation_audit_pipeline.py +83 -0
- package/examples/python-sdk/incident_triage_pipeline.py +170 -0
- package/examples/python-sdk/multi_agent_pipeline.py +95 -0
- package/examples/python-sdk/platform_provisioning_pipeline.py +193 -0
- package/examples/python-sdk/release_readiness_audit.py +144 -0
- package/hooks/secret-scrubber/hooks.json +16 -0
- package/hooks/secret-scrubber/scripts/scrub-secrets.sh +62 -0
- package/mcp/README.md +21 -0
- package/mcp/mcp_config.example.json +39 -0
- package/package.json +3 -1
- package/plugins/core/rules/core-practices.md +63 -4
- package/plugins/python-ai/rules/ai-agent-patterns.md +67 -4
- package/plugins/security-shield/rules/zero-trust.md +60 -4
- package/plugins/web-fullstack/rules/frontend-standards.md +74 -4
- package/rules/paradigms/security-hardened.md +53 -10
- package/rules/paradigms/tdd.md +65 -8
- package/scripts/install.ps1 +14 -0
- package/scripts/install.sh +15 -1
- package/scripts/validate.sh +103 -12
- package/skills/apache-kafka-streams/SKILL.md +152 -0
- package/skills/argo-workflows/SKILL.md +151 -0
- package/skills/axum-web-service/SKILL.md +159 -0
- package/skills/cilium-ebpf-networking/SKILL.md +145 -0
- package/skills/clickhouse-analytics/SKILL.md +128 -0
- package/skills/cloudflare-r2-object-storage/SKILL.md +143 -0
- package/skills/dbt-transformation/SKILL.md +179 -0
- package/skills/debezium-cdc/SKILL.md +166 -0
- package/skills/distributed-rate-limiting/SKILL.md +138 -0
- package/skills/duckdb-local-olap/SKILL.md +134 -0
- package/skills/fastapi-production/SKILL.md +157 -0
- package/skills/grpc-connect-rpc/SKILL.md +176 -0
- package/skills/langgraph-orchestrator/SKILL.md +144 -0
- package/skills/litellm-proxy-gateway/SKILL.md +154 -0
- package/skills/milvus-vector-clustering/SKILL.md +134 -0
- package/skills/nats-jetstream/SKILL.md +122 -0
- package/skills/open-telemetry-tracing/SKILL.md +151 -0
- package/skills/playwright-visual-regression/SKILL.md +124 -0
- package/skills/redis-cache-patterns/SKILL.md +159 -0
- package/skills/svelte-kit-architect/SKILL.md +190 -0
- package/skills/temporal-workflows/SKILL.md +158 -0
- package/skills/trpc-react-query/SKILL.md +169 -0
- package/skills/turborepo-monorepo/SKILL.md +199 -0
- package/skills/vault-secrets-management/SKILL.md +129 -0
- package/skills/vllm-inference/SKILL.md +144 -0
- package/skills/wasm-rust-optimizer/SKILL.md +130 -0
- package/templates/full-power/hooks.json +14 -0
- package/templates/full-power/mcp_config.json +47 -0
- package/templates/recommended/hooks.json +14 -0
- package/tests/cli.test.js +447 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything Gemini CLI End-to-End Integration Test Suite
|
|
3
|
+
* Validates CLI subcommands, dry-run simulation, and JSON output formatting.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const assert = require('assert');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
|
|
12
|
+
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
13
|
+
const CLI_PATH = path.join(REPO_ROOT, 'bin', 'everything-gemini');
|
|
14
|
+
|
|
15
|
+
function stripAnsi(str) {
|
|
16
|
+
return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function runCli(args, env = {}) {
|
|
20
|
+
const cmd = `node "${CLI_PATH}" ${args}`;
|
|
21
|
+
try {
|
|
22
|
+
const rawStdout = execSync(cmd, {
|
|
23
|
+
cwd: REPO_ROOT,
|
|
24
|
+
encoding: 'utf8',
|
|
25
|
+
env: { ...process.env, ...env }
|
|
26
|
+
});
|
|
27
|
+
return { status: 0, stdout: stripAnsi(rawStdout), rawStdout, stderr: '' };
|
|
28
|
+
} catch (err) {
|
|
29
|
+
return {
|
|
30
|
+
status: err.status || 1,
|
|
31
|
+
stdout: err.stdout ? stripAnsi(err.stdout.toString()) : '',
|
|
32
|
+
rawStdout: err.stdout ? err.stdout.toString() : '',
|
|
33
|
+
stderr: err.stderr ? err.stderr.toString() : err.message
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log('🧪 Starting Everything Gemini CLI E2E Tests...\n');
|
|
39
|
+
|
|
40
|
+
let testsPassed = 0;
|
|
41
|
+
let testsFailed = 0;
|
|
42
|
+
|
|
43
|
+
function it(name, fn) {
|
|
44
|
+
try {
|
|
45
|
+
fn();
|
|
46
|
+
console.log(` ✔ ${name}`);
|
|
47
|
+
testsPassed++;
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.error(` ✖ ${name}`);
|
|
50
|
+
console.error(` ${err.message}`);
|
|
51
|
+
testsFailed++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 1. Doctor
|
|
56
|
+
it('should run doctor successfully', () => {
|
|
57
|
+
const res = runCli('doctor');
|
|
58
|
+
assert.strictEqual(res.status, 0);
|
|
59
|
+
assert.match(res.stdout, /Running Antigravity & Environment Diagnostics/);
|
|
60
|
+
assert.match(res.stdout, /Node\.js runtime/);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// 2. List
|
|
64
|
+
it('should list all components across catalog', () => {
|
|
65
|
+
const res = runCli('list');
|
|
66
|
+
assert.strictEqual(res.status, 0);
|
|
67
|
+
assert.match(res.stdout, /Everything Gemini Catalog/);
|
|
68
|
+
assert.match(res.stdout, /gemini-multimodal/);
|
|
69
|
+
assert.match(res.stdout, /code-reviewer/);
|
|
70
|
+
assert.match(res.stdout, /safety-shield/);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// 3. Info / Show
|
|
74
|
+
it('should display info for a progressive skill', () => {
|
|
75
|
+
const res = runCli('info agent-evals');
|
|
76
|
+
assert.strictEqual(res.status, 0);
|
|
77
|
+
assert.match(res.stdout, /Skill Overview: agent-evals/);
|
|
78
|
+
assert.match(res.stdout, /Trigger Description/);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should display info for a scoped subagent', () => {
|
|
82
|
+
const res = runCli('info planner');
|
|
83
|
+
assert.strictEqual(res.status, 0);
|
|
84
|
+
assert.match(res.stdout, /Subagent Specification: planner/);
|
|
85
|
+
assert.match(res.stdout, /Scoped Subagent: Strategic Planner/);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// 4. Benchmark & Test-All with JSON
|
|
89
|
+
it('should benchmark ecosystem components and output valid JSON with --json', () => {
|
|
90
|
+
const res = runCli('benchmark --json');
|
|
91
|
+
assert.strictEqual(res.status, 0);
|
|
92
|
+
const data = JSON.parse(res.stdout);
|
|
93
|
+
assert.strictEqual(data.totalComponents, 75);
|
|
94
|
+
assert.strictEqual(data.progressiveSkillsCount, 56);
|
|
95
|
+
assert.strictEqual(data.scopedAgentsCount, 12);
|
|
96
|
+
assert.strictEqual(data.lifecycleHooksCount, 7);
|
|
97
|
+
assert(data.totalRunbookTokens > 15000, 'Expected >15,000 runbook tokens');
|
|
98
|
+
assert(data.estimatedTokensSavedPerTurn > 8000, 'Expected significant token savings');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// 5. Completion
|
|
102
|
+
it('should generate shell autocompletion script', () => {
|
|
103
|
+
const res = runCli('completion');
|
|
104
|
+
assert.strictEqual(res.status, 0);
|
|
105
|
+
assert.match(res.stdout, /_everything_gemini\(\)/);
|
|
106
|
+
assert.match(res.stdout, /complete -F _everything_gemini/);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should support completion --install --dry-run', () => {
|
|
110
|
+
const res = runCli('completion --install --dry-run');
|
|
111
|
+
assert.strictEqual(res.status, 0);
|
|
112
|
+
assert.match(res.stdout, /DRY RUN/);
|
|
113
|
+
assert.match(res.stdout, /Would append completion script/);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 6. Sandboxed Workspace Tests
|
|
117
|
+
const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'egemini-test-'));
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
it('should install completion script idempotently to a custom rc file', () => {
|
|
121
|
+
const customRc = path.join(tempWorkspace, 'test.bashrc');
|
|
122
|
+
fs.writeFileSync(customRc, '# existing rc\n');
|
|
123
|
+
const res1 = runCli(`completion --install --rc "${customRc}"`);
|
|
124
|
+
assert.strictEqual(res1.status, 0);
|
|
125
|
+
assert.match(res1.stdout, /Successfully installed autocompletion/);
|
|
126
|
+
assert(fs.readFileSync(customRc, 'utf8').includes('_everything_gemini()'));
|
|
127
|
+
|
|
128
|
+
// Test idempotency
|
|
129
|
+
const res2 = runCli(`completion --install --rc "${customRc}"`);
|
|
130
|
+
assert.strictEqual(res2.status, 0);
|
|
131
|
+
assert.match(res2.stdout, /already configured/);
|
|
132
|
+
});
|
|
133
|
+
// Dry run installation
|
|
134
|
+
it('should support --dry-run on install without creating directories', () => {
|
|
135
|
+
const dryWorkspace = path.join(tempWorkspace, 'dry-run-workspace');
|
|
136
|
+
const res = runCli(`install --workspace "${dryWorkspace}" --profile developer --dry-run`);
|
|
137
|
+
assert.strictEqual(res.status, 0);
|
|
138
|
+
assert.match(res.stdout, /DRY RUN MODE ACTIVATED/);
|
|
139
|
+
assert.match(res.stdout, /Would install/);
|
|
140
|
+
assert.strictEqual(fs.existsSync(dryWorkspace), false, 'Dry run should not create target workspace');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Real installation
|
|
144
|
+
it('should install developer profile into custom workspace', () => {
|
|
145
|
+
const res = runCli(`install --workspace "${tempWorkspace}" --profile developer`);
|
|
146
|
+
assert.strictEqual(res.status, 0);
|
|
147
|
+
assert.match(res.stdout, /Installation complete/);
|
|
148
|
+
assert.strictEqual(fs.existsSync(path.join(tempWorkspace, 'GEMINI.md')), true);
|
|
149
|
+
assert.strictEqual(fs.existsSync(path.join(tempWorkspace, 'AGENTS.md')), true);
|
|
150
|
+
assert.strictEqual(fs.existsSync(path.join(tempWorkspace, 'skills', 'tdd-workflow', 'SKILL.md')), true);
|
|
151
|
+
assert.strictEqual(fs.existsSync(path.join(tempWorkspace, 'hooks.json')), true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Status check (Human & JSON)
|
|
155
|
+
it('should report workspace status in human format', () => {
|
|
156
|
+
const res = runCli(`status --workspace "${tempWorkspace}"`);
|
|
157
|
+
assert.strictEqual(res.status, 0);
|
|
158
|
+
assert.match(res.stdout, /Everything Gemini Workspace Status/);
|
|
159
|
+
assert.match(res.stdout, /GEMINI\.md \(active\)/);
|
|
160
|
+
assert.match(res.stdout, /Installed Skills/);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should report workspace status in structured JSON format with --json', () => {
|
|
164
|
+
const res = runCli(`status --workspace "${tempWorkspace}" --json`);
|
|
165
|
+
assert.strictEqual(res.status, 0);
|
|
166
|
+
const data = JSON.parse(res.stdout);
|
|
167
|
+
assert.strictEqual(data.isInitialized, true);
|
|
168
|
+
assert.strictEqual(data.rules.gemini, true);
|
|
169
|
+
assert.strictEqual(data.rules.agents, true);
|
|
170
|
+
assert(data.skills.installedCount >= 10, 'Expected at least 10 skills in developer profile');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Add & Remove component
|
|
174
|
+
it('should dynamically add and remove a skill to active workspace', () => {
|
|
175
|
+
const addRes = runCli(`add skill stripe-integration --workspace "${tempWorkspace}"`);
|
|
176
|
+
assert.strictEqual(addRes.status, 0);
|
|
177
|
+
assert.strictEqual(fs.existsSync(path.join(tempWorkspace, 'skills', 'stripe-integration', 'SKILL.md')), true);
|
|
178
|
+
|
|
179
|
+
const removeRes = runCli(`remove skill stripe-integration --workspace "${tempWorkspace}"`);
|
|
180
|
+
assert.strictEqual(removeRes.status, 0);
|
|
181
|
+
assert.strictEqual(fs.existsSync(path.join(tempWorkspace, 'skills', 'stripe-integration')), false);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Update in dry-run and live
|
|
185
|
+
it('should support --dry-run on update without modifications', () => {
|
|
186
|
+
const res = runCli(`update --workspace "${tempWorkspace}" --dry-run`);
|
|
187
|
+
assert.strictEqual(res.status, 0);
|
|
188
|
+
assert.match(res.stdout, /DRY RUN MODE ACTIVATED/);
|
|
189
|
+
assert.match(res.stdout, /Would update skill/);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('should update installed workspace components cleanly', () => {
|
|
193
|
+
const res = runCli(`update --workspace "${tempWorkspace}"`);
|
|
194
|
+
assert.strictEqual(res.status, 0);
|
|
195
|
+
assert.match(res.stdout, /Update complete/);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Diff Command
|
|
199
|
+
it('should run diff against workspace', () => {
|
|
200
|
+
const res = runCli(`diff --workspace "${tempWorkspace}"`);
|
|
201
|
+
assert.strictEqual(res.status, 0);
|
|
202
|
+
assert.match(res.stdout, /Comparing Workspace vs\. Master Everything Gemini Catalog/);
|
|
203
|
+
assert.match(res.stdout, /Progressive Skills Comparison/);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Export Command
|
|
207
|
+
it('should export workspace configuration bundle to JSON', () => {
|
|
208
|
+
const exportFile = path.join(tempWorkspace, 'exported-profile.json');
|
|
209
|
+
const res = runCli(`export --workspace "${tempWorkspace}" --output "${exportFile}"`);
|
|
210
|
+
assert.strictEqual(res.status, 0);
|
|
211
|
+
assert.match(res.stdout, /Exporting Agent Configuration Bundle/);
|
|
212
|
+
assert.strictEqual(fs.existsSync(exportFile), true, 'Export file should exist');
|
|
213
|
+
const data = JSON.parse(fs.readFileSync(exportFile, 'utf8'));
|
|
214
|
+
assert.strictEqual(data.generator, 'everything-gemini');
|
|
215
|
+
assert(data.skills.length > 0, 'Exported bundle should contain skills');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Info for newly added subagents and skills
|
|
219
|
+
it('should display info for database-migrator subagent and clickhouse-analytics skill', () => {
|
|
220
|
+
const res1 = runCli('info database-migrator');
|
|
221
|
+
assert.strictEqual(res1.status, 0);
|
|
222
|
+
assert.match(res1.stdout, /Database Migrator/);
|
|
223
|
+
|
|
224
|
+
const res2 = runCli('info clickhouse-analytics');
|
|
225
|
+
assert.strictEqual(res2.status, 0);
|
|
226
|
+
assert.match(res2.stdout, /ClickHouse Analytics/);
|
|
227
|
+
|
|
228
|
+
const res3 = runCli('info duckdb-local-olap');
|
|
229
|
+
assert.strictEqual(res3.status, 0);
|
|
230
|
+
assert.match(res3.stdout, /DuckDB Local OLAP/);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Import Command
|
|
234
|
+
it('should import agent configuration bundle cleanly', () => {
|
|
235
|
+
const exportFile = path.join(tempWorkspace, 'exported-profile.json');
|
|
236
|
+
const importWorkspace = path.join(tempWorkspace, 'imported-workspace');
|
|
237
|
+
|
|
238
|
+
// Dry run
|
|
239
|
+
const dryRes = runCli(`import "${exportFile}" --workspace "${importWorkspace}" --dry-run`);
|
|
240
|
+
assert.strictEqual(dryRes.status, 0);
|
|
241
|
+
assert.match(dryRes.stdout, /DRY RUN MODE ACTIVATED/);
|
|
242
|
+
assert.match(dryRes.stdout, /Would import/);
|
|
243
|
+
|
|
244
|
+
// Live import
|
|
245
|
+
const liveRes = runCli(`import "${exportFile}" --workspace "${importWorkspace}"`);
|
|
246
|
+
assert.strictEqual(liveRes.status, 0);
|
|
247
|
+
assert.match(liveRes.stdout, /Import complete/);
|
|
248
|
+
assert.strictEqual(fs.existsSync(path.join(importWorkspace, 'skills')), true);
|
|
249
|
+
assert.strictEqual(fs.existsSync(path.join(importWorkspace, 'hooks.json')), true);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Search Command
|
|
253
|
+
it('should search components with human and JSON output', () => {
|
|
254
|
+
const humanRes = runCli('search kafka');
|
|
255
|
+
assert.strictEqual(humanRes.status, 0);
|
|
256
|
+
assert.match(humanRes.stdout, /apache-kafka-streams/);
|
|
257
|
+
assert.match(humanRes.stdout, /Search Results for/);
|
|
258
|
+
|
|
259
|
+
const jsonRes = runCli('search dbt --json');
|
|
260
|
+
assert.strictEqual(jsonRes.status, 0);
|
|
261
|
+
const data = JSON.parse(jsonRes.stdout);
|
|
262
|
+
assert.strictEqual(data.query, 'dbt');
|
|
263
|
+
assert(data.results.skills.some(s => s.name === 'dbt-transformation'));
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Audit Command
|
|
267
|
+
it('should audit workspace and catalog with human and JSON output', () => {
|
|
268
|
+
const humanRes = runCli('audit .');
|
|
269
|
+
assert.strictEqual(humanRes.status, 0);
|
|
270
|
+
assert.match(humanRes.stdout, /Everything Gemini Ecosystem Audit Report/);
|
|
271
|
+
assert.match(humanRes.stdout, /ALL CHECKS PASSED/);
|
|
272
|
+
|
|
273
|
+
const jsonRes = runCli('audit . --json');
|
|
274
|
+
assert.strictEqual(jsonRes.status, 0);
|
|
275
|
+
const data = JSON.parse(jsonRes.stdout);
|
|
276
|
+
assert.strictEqual(data.valid, true);
|
|
277
|
+
assert.strictEqual(data.errorCount, 0);
|
|
278
|
+
assert(data.passedCount > 50, 'Audit should run at least 50 checks');
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Info for documentation-writer and v1.6.0 skills
|
|
282
|
+
it('should display info for documentation-writer subagent and v1.6.0 skills', () => {
|
|
283
|
+
const resDoc = runCli('info documentation-writer');
|
|
284
|
+
assert.strictEqual(resDoc.status, 0);
|
|
285
|
+
assert.match(resDoc.stdout, /Documentation Writer/);
|
|
286
|
+
|
|
287
|
+
const resTurbo = runCli('info turborepo-monorepo');
|
|
288
|
+
assert.strictEqual(resTurbo.status, 0);
|
|
289
|
+
assert.match(resTurbo.stdout, /Turborepo/);
|
|
290
|
+
|
|
291
|
+
const resRpc = runCli('info grpc-connect-rpc');
|
|
292
|
+
assert.strictEqual(resRpc.status, 0);
|
|
293
|
+
assert.match(resRpc.stdout, /Connect-RPC/);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Info for release-engineer and v1.7.0 skills
|
|
297
|
+
it('should display info for release-engineer subagent and v1.7.0 skills', () => {
|
|
298
|
+
const resRel = runCli('info release-engineer');
|
|
299
|
+
assert.strictEqual(resRel.status, 0);
|
|
300
|
+
assert.match(resRel.stdout, /Release Engineer/);
|
|
301
|
+
|
|
302
|
+
const resLang = runCli('info langgraph-orchestrator');
|
|
303
|
+
assert.strictEqual(resLang.status, 0);
|
|
304
|
+
assert.match(resLang.stdout, /LangGraph/);
|
|
305
|
+
|
|
306
|
+
const resOtel = runCli('info open-telemetry-tracing');
|
|
307
|
+
assert.strictEqual(resOtel.status, 0);
|
|
308
|
+
assert.match(resOtel.stdout, /OpenTelemetry/);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Bundle Command
|
|
312
|
+
it('should package offline distribution bundle in dry-run and live modes', () => {
|
|
313
|
+
const bundleTarget = path.join(tempWorkspace, 'test-bundle');
|
|
314
|
+
|
|
315
|
+
// Dry-run mode
|
|
316
|
+
const dryRes = runCli(`bundle --output "${bundleTarget}" --dry-run`);
|
|
317
|
+
assert.strictEqual(dryRes.status, 0);
|
|
318
|
+
assert.match(dryRes.stdout, /DRY RUN MODE ACTIVATED/);
|
|
319
|
+
assert.match(dryRes.stdout, /Skills to bundle: 56/);
|
|
320
|
+
assert.strictEqual(fs.existsSync(bundleTarget), false, 'Dry run should not create destination directory');
|
|
321
|
+
|
|
322
|
+
// JSON Dry-run mode
|
|
323
|
+
const jsonRes = runCli(`bundle --output "${bundleTarget}" --dry-run --json`);
|
|
324
|
+
assert.strictEqual(jsonRes.status, 0);
|
|
325
|
+
const dryData = JSON.parse(jsonRes.stdout);
|
|
326
|
+
assert.strictEqual(dryData.dryRun, true);
|
|
327
|
+
assert.strictEqual(dryData.manifest.components.totalCount, 75);
|
|
328
|
+
|
|
329
|
+
// Live mode
|
|
330
|
+
const liveRes = runCli(`bundle --output "${bundleTarget}"`);
|
|
331
|
+
assert.strictEqual(liveRes.status, 0);
|
|
332
|
+
assert.match(liveRes.stdout, /Offline Distribution Bundle Created/);
|
|
333
|
+
assert.strictEqual(fs.existsSync(path.join(bundleTarget, 'bundle-manifest.json')), true);
|
|
334
|
+
assert.strictEqual(fs.existsSync(path.join(bundleTarget, 'offline-install.sh')), true);
|
|
335
|
+
assert.strictEqual(fs.existsSync(path.join(bundleTarget, 'skills', 'milvus-vector-clustering')), true);
|
|
336
|
+
assert.strictEqual(fs.existsSync(path.join(bundleTarget, 'agents', 'platform-engineer.md')), true);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// Scaffold Command
|
|
340
|
+
it('should scaffold skill, agent, and hook in dry-run and live modes', () => {
|
|
341
|
+
const scaffoldWorkspace = path.join(tempWorkspace, 'scaffold-ws');
|
|
342
|
+
|
|
343
|
+
// Skill Dry-run
|
|
344
|
+
const drySkill = runCli(`scaffold skill demo-test-skill --workspace "${scaffoldWorkspace}" --dry-run --json`);
|
|
345
|
+
assert.strictEqual(drySkill.status, 0);
|
|
346
|
+
const drySkillData = JSON.parse(drySkill.stdout);
|
|
347
|
+
assert.strictEqual(drySkillData.isDryRun, true);
|
|
348
|
+
assert.strictEqual(drySkillData.type, 'skill');
|
|
349
|
+
|
|
350
|
+
// Live Agent Scaffold
|
|
351
|
+
const liveAgent = runCli(`scaffold agent demo-qa-agent --workspace "${scaffoldWorkspace}"`);
|
|
352
|
+
assert.strictEqual(liveAgent.status, 0);
|
|
353
|
+
assert.match(liveAgent.stdout, /Created subagent profile/);
|
|
354
|
+
assert.strictEqual(fs.existsSync(path.join(scaffoldWorkspace, 'agents', 'demo-qa-agent.md')), true);
|
|
355
|
+
|
|
356
|
+
// Live Hook Scaffold
|
|
357
|
+
const liveHook = runCli(`scaffold hook demo-safety --workspace "${scaffoldWorkspace}"`);
|
|
358
|
+
assert.strictEqual(liveHook.status, 0);
|
|
359
|
+
assert.match(liveHook.stdout, /Created lifecycle hook/);
|
|
360
|
+
assert.strictEqual(fs.existsSync(path.join(scaffoldWorkspace, 'hooks', 'demo-safety', 'hooks.json')), true);
|
|
361
|
+
assert.strictEqual(fs.existsSync(path.join(scaffoldWorkspace, 'hooks', 'demo-safety', 'scripts', 'demo-safety-gate.sh')), true);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// Sync Command
|
|
365
|
+
it('should synchronize workspace with sync command in dry-run and live modes', () => {
|
|
366
|
+
// Dry-run
|
|
367
|
+
const drySync = runCli(`sync --workspace "${tempWorkspace}" --dry-run`);
|
|
368
|
+
assert.strictEqual(drySync.status, 0);
|
|
369
|
+
assert.match(drySync.stdout, /DRY RUN MODE ACTIVATED/);
|
|
370
|
+
assert.match(drySync.stdout, /Synchronizing Workspace with Catalog/);
|
|
371
|
+
|
|
372
|
+
// JSON Dry-run
|
|
373
|
+
const jsonSync = runCli(`sync --workspace "${tempWorkspace}" --dry-run --json`);
|
|
374
|
+
assert.strictEqual(jsonSync.status, 0);
|
|
375
|
+
const syncData = JSON.parse(jsonSync.stdout);
|
|
376
|
+
assert.strictEqual(syncData.isDryRun, true);
|
|
377
|
+
assert.strictEqual(syncData.success, true);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Info for incident-responder and v1.8.0 skills
|
|
381
|
+
it('should display info for incident-responder subagent and v1.8.0 skills', () => {
|
|
382
|
+
const resInc = runCli('info incident-responder');
|
|
383
|
+
assert.strictEqual(resInc.status, 0);
|
|
384
|
+
assert.match(resInc.stdout, /Incident Responder/);
|
|
385
|
+
|
|
386
|
+
const resVllm = runCli('info vllm-inference');
|
|
387
|
+
assert.strictEqual(resVllm.status, 0);
|
|
388
|
+
assert.match(resVllm.stdout, /vLLM/);
|
|
389
|
+
|
|
390
|
+
const resCdc = runCli('info debezium-cdc');
|
|
391
|
+
assert.strictEqual(resCdc.status, 0);
|
|
392
|
+
assert.match(resCdc.stdout, /Debezium/);
|
|
393
|
+
|
|
394
|
+
const resCilium = runCli('info cilium-ebpf-networking');
|
|
395
|
+
assert.strictEqual(resCilium.status, 0);
|
|
396
|
+
assert.match(resCilium.stdout, /Cilium/);
|
|
397
|
+
|
|
398
|
+
const resLite = runCli('info litellm-proxy-gateway');
|
|
399
|
+
assert.strictEqual(resLite.status, 0);
|
|
400
|
+
assert.match(resLite.stdout, /LiteLLM/);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Info for platform-engineer and v1.9.0 skills
|
|
404
|
+
it('should display info for platform-engineer subagent and v1.9.0 skills', () => {
|
|
405
|
+
const resPlat = runCli('info platform-engineer');
|
|
406
|
+
assert.strictEqual(resPlat.status, 0);
|
|
407
|
+
assert.match(resPlat.stdout, /Platform Engineer/);
|
|
408
|
+
|
|
409
|
+
const resMilvus = runCli('info milvus-vector-clustering');
|
|
410
|
+
assert.strictEqual(resMilvus.status, 0);
|
|
411
|
+
assert.match(resMilvus.stdout, /Milvus/);
|
|
412
|
+
|
|
413
|
+
const resR2 = runCli('info cloudflare-r2-object-storage');
|
|
414
|
+
assert.strictEqual(resR2.status, 0);
|
|
415
|
+
assert.match(resR2.stdout, /Cloudflare R2/);
|
|
416
|
+
|
|
417
|
+
const resVault = runCli('info vault-secrets-management');
|
|
418
|
+
assert.strictEqual(resVault.status, 0);
|
|
419
|
+
assert.match(resVault.stdout, /Vault/);
|
|
420
|
+
|
|
421
|
+
const resRate = runCli('info distributed-rate-limiting');
|
|
422
|
+
assert.strictEqual(resRate.status, 0);
|
|
423
|
+
assert.match(resRate.stdout, /Distributed Rate Limiting/);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Benchmark Components Verification
|
|
427
|
+
it('should report 75 components, 56 skills, and 12 subagents in benchmark --json', () => {
|
|
428
|
+
const res = runCli('benchmark --json');
|
|
429
|
+
assert.strictEqual(res.status, 0);
|
|
430
|
+
const data = JSON.parse(res.stdout);
|
|
431
|
+
assert.strictEqual(data.totalComponents, 75, 'Total components should be 75');
|
|
432
|
+
assert.strictEqual(data.progressiveSkillsCount, 56, 'Progressive skills should be 56');
|
|
433
|
+
assert.strictEqual(data.scopedAgentsCount, 12, 'Scoped agents should be 12');
|
|
434
|
+
assert.strictEqual(data.lifecycleHooksCount, 7, 'Lifecycle hooks should be 7');
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
} finally {
|
|
438
|
+
try {
|
|
439
|
+
fs.rmSync(tempWorkspace, { recursive: true, force: true });
|
|
440
|
+
} catch (_) {}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
console.log(`\n✨ Test Run Finished: ${testsPassed} passed, ${testsFailed} failed.`);
|
|
444
|
+
|
|
445
|
+
if (testsFailed > 0) {
|
|
446
|
+
process.exit(1);
|
|
447
|
+
}
|