berget 2.2.11 → 2.2.12

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.
@@ -1,507 +1,29 @@
1
1
  import { Command } from 'commander';
2
- import * as fs from 'node:fs';
3
- import { readFile, writeFile } from 'node:fs/promises';
4
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { beforeEach, describe, expect, it } from 'vitest';
5
3
 
6
4
  import { registerCodeCommands } from '../../src/commands/code';
7
- import { ApiKeyService } from '../../src/services/api-key-service';
8
- import { updateEnvFile as updateEnvironmentFile } from '../../src/utils/env-manager';
9
-
10
- // Mock dependencies
11
- vi.mock('../../src/services/api-key-service');
12
- vi.mock('fs', () => ({
13
- default: {
14
- existsSync: vi.fn(),
15
- readFileSync: vi.fn(),
16
- },
17
- }));
18
- vi.mock('fs/promises', () => ({
19
- readFile: vi.fn(),
20
- writeFile: vi.fn(),
21
- }));
22
- vi.mock('../../src/utils/env-manager');
23
- vi.mock('child_process', () => ({
24
- spawn: vi.fn(),
25
- }));
26
- vi.mock('readline', () => ({
27
- createInterface: vi.fn(() => ({
28
- close: vi.fn(),
29
- question: vi.fn(),
30
- })),
31
- }));
32
5
 
33
6
  describe('Code Commands', () => {
34
7
  let program: Command;
35
- let mockApiKeyService: any;
36
- let mockFs: any;
37
- let mockFsPromises: any;
38
- let mockSpawn: any;
39
8
 
40
9
  beforeEach(() => {
41
10
  program = new Command();
42
-
43
- // Mock ApiKeyService
44
- mockApiKeyService = {
45
- create: vi.fn(),
46
- list: vi.fn(),
47
- rotate: vi.fn(),
48
- };
49
- vi.mocked(ApiKeyService.getInstance).mockReturnValue(mockApiKeyService);
50
-
51
- // Mock fs
52
- mockFs = vi.mocked(fs);
53
- mockFs.existsSync = vi.fn();
54
- mockFs.readFileSync = vi.fn();
55
-
56
- // Mock fs/promises
57
- mockFsPromises = vi.mocked({ readFile, writeFile });
58
- mockFsPromises.readFile = vi.fn();
59
- mockFsPromises.writeFile = vi.fn();
60
-
61
- // Mock spawn
62
- mockSpawn = vi.fn();
63
- vi.doMock('child_process', () => ({ spawn: mockSpawn }));
64
-
65
11
  registerCodeCommands(program);
66
12
  });
67
13
 
68
- afterEach(() => {
69
- vi.clearAllMocks();
70
- });
71
-
72
14
  describe('code init command', () => {
73
15
  it('should register init command with correct description', () => {
74
16
  const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
75
17
  const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
76
18
 
77
19
  expect(initCommand).toBeDefined();
78
- expect(initCommand?.description()).toBe('Initialize project for AI coding assistant');
79
- });
80
-
81
- it('should have name, force, and yes options', () => {
82
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
83
- const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
84
-
85
- expect(initCommand).toBeDefined();
86
-
87
- const nameOption = initCommand?.options.find((opt) => opt.long === '--name');
88
- const forceOption = initCommand?.options.find((opt) => opt.long === '--force');
89
- const yesOption = initCommand?.options.find((opt) => opt.long === '--yes');
90
-
91
- expect(nameOption).toBeDefined();
92
- expect(nameOption?.description).toContain('Project name');
93
- expect(forceOption).toBeDefined();
94
- expect(forceOption?.description).toContain('Overwrite existing configuration');
95
- expect(yesOption).toBeDefined();
96
- expect(yesOption?.description).toContain('Automatically answer yes');
97
- });
98
-
99
- it('should check if opencode is installed', () => {
100
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
101
- const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
102
-
103
- expect(initCommand).toBeDefined();
104
-
105
- // The command should attempt to spawn opencode --version
106
- // This is tested implicitly through the spawn mock
107
- });
108
-
109
- it('should list existing API keys and allow selection', async () => {
110
- // Mock successful opencode installation check
111
- mockSpawn.mockImplementation((command: string, arguments_: string[]) => {
112
- if (command === 'opencode' && arguments_[0] === '--version') {
113
- return {
114
- on: vi.fn().mockImplementation((event, callback) => {
115
- if (event === 'close') callback(0);
116
- }),
117
- };
118
- }
119
- return { on: vi.fn() };
120
- });
121
-
122
- // Mock existing API keys
123
- const mockExistingKeys = [
124
- {
125
- created: '2023-01-01T00:00:00.000Z',
126
- id: 1,
127
- lastUsed: null,
128
- name: 'existing-key-1',
129
- prefix: 'sk_ber',
130
- },
131
- {
132
- created: '2023-01-02T00:00:00.000Z',
133
- id: 2,
134
- lastUsed: '2023-01-03T00:00:00.000Z',
135
- name: 'existing-key-2',
136
- prefix: 'sk_ber',
137
- },
138
- ];
139
- mockApiKeyService.list.mockResolvedValue(mockExistingKeys);
140
-
141
- // Mock file operations
142
- mockFs.existsSync.mockReturnValue(false);
143
- mockFsPromises.writeFile.mockResolvedValue();
144
-
145
- // Verify that the list method is called
146
- expect(mockApiKeyService.list).toBeDefined();
147
- });
148
-
149
- it('should create new API key with project-based naming', async () => {
150
- // Mock successful opencode installation check
151
- mockSpawn.mockImplementation((command: string, arguments_: string[]) => {
152
- if (command === 'opencode' && arguments_[0] === '--version') {
153
- return {
154
- on: vi.fn().mockImplementation((event, callback) => {
155
- if (event === 'close') callback(0);
156
- }),
157
- };
158
- }
159
- return { on: vi.fn() };
160
- });
161
-
162
- // Mock no existing keys
163
- mockApiKeyService.list.mockResolvedValue([]);
164
-
165
- // Mock successful API key creation
166
- const mockApiKeyData = {
167
- id: 123,
168
- key: 'test-api-key-12345',
169
- name: 'opencode-testproject-1234567890',
170
- };
171
- mockApiKeyService.create.mockResolvedValue(mockApiKeyData);
172
-
173
- // Mock file operations
174
- mockFs.existsSync.mockReturnValue(false);
175
- mockFsPromises.writeFile.mockResolvedValue();
176
-
177
- // Verify that the create method is available
178
- expect(mockApiKeyService.create).toBeDefined();
179
- });
180
-
181
- it('should create opencode.json with correct structure', async () => {
182
- // This tests the expected config structure
183
- const expectedConfig = {
184
- apiKey: 'test-api-key',
185
- created: expect.any(String),
186
- model: 'berget/glm-4-6',
187
- projectName: 'testproject',
188
- provider: 'berget',
189
- version: '1.0.0',
190
- };
191
-
192
- expect(expectedConfig.model).toBe('berget/glm-4-6');
193
- expect(expectedConfig.provider).toBe('berget');
194
- expect(expectedConfig.version).toBe('1.0.0');
195
- });
196
-
197
- it('should handle existing config file', () => {
198
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
199
- const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
200
-
201
- expect(initCommand).toBeDefined();
202
-
203
- // Should check if opencode.json exists before proceeding
204
- expect(mockFs.existsSync).toBeDefined();
205
- });
206
- });
207
-
208
- describe('code run command', () => {
209
- it('should register run command with correct description', () => {
210
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
211
- const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
212
-
213
- expect(runCommand).toBeDefined();
214
- expect(runCommand?.description()).toBe('Run AI coding assistant');
215
- });
216
-
217
- it('should accept prompt argument and model, no-config, and yes options', () => {
218
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
219
- const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
220
-
221
- expect(runCommand).toBeDefined();
222
-
223
- const modelOption = runCommand?.options.find((opt) => opt.long === '--model');
224
- const noConfigOption = runCommand?.options.find((opt) => opt.long === '--no-config');
225
- const yesOption = runCommand?.options.find((opt) => opt.long === '--yes');
226
-
227
- expect(modelOption).toBeDefined();
228
- expect(modelOption?.description).toContain('Model to use');
229
- expect(noConfigOption).toBeDefined();
230
- expect(noConfigOption?.description).toContain('Run without loading project config');
231
- expect(yesOption).toBeDefined();
232
- expect(yesOption?.description).toContain('Automatically answer yes');
233
- });
234
-
235
- it('should load configuration from opencode.json', async () => {
236
- const mockConfig = {
237
- apiKey: 'test-api-key',
238
- created: '2023-01-01T00:00:00.000Z',
239
- model: 'berget/glm-4-6',
240
- projectName: 'testproject',
241
- provider: 'berget',
242
- version: '1.0.0',
243
- };
244
-
245
- // Mock file exists and contains config
246
- mockFs.existsSync.mockReturnValue(true);
247
- mockFsPromises.readFile.mockResolvedValue(JSON.stringify(mockConfig));
248
-
249
- // Mock successful opencode check
250
- mockSpawn.mockImplementation((command: string, arguments_: string[]) => {
251
- if (command === 'opencode' && arguments_[0] === '--version') {
252
- return {
253
- on: vi.fn().mockImplementation((event, callback) => {
254
- if (event === 'close') callback(0);
255
- }),
256
- };
257
- }
258
- return { on: vi.fn() };
259
- });
260
-
261
- // Verify config structure expectations
262
- expect(mockConfig.model).toBe('berget/glm-4-6');
263
- expect(mockConfig.apiKey).toBe('test-api-key');
264
- expect(mockConfig.projectName).toBe('testproject');
265
- });
266
-
267
- it('should spawn opencode with correct arguments', () => {
268
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
269
- const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
270
-
271
- expect(runCommand).toBeDefined();
272
-
273
- // Should spawn opencode with appropriate arguments
274
- expect(mockSpawn).toBeDefined();
20
+ expect(initCommand?.description()).toBe('Interactive setup for Berget AI coding tools');
275
21
  });
276
22
 
277
- it('should handle missing configuration file', () => {
23
+ it('should not have any other subcommands', () => {
278
24
  const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
279
- const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
280
-
281
- expect(runCommand).toBeDefined();
282
-
283
- // Should check if opencode.json exists
284
- expect(mockFs.existsSync).toBeDefined();
285
- });
286
- });
287
-
288
- describe('opencode installation', () => {
289
- it('should check if opencode is installed', () => {
290
- // The spawn function should be called with opencode --version
291
- expect(mockSpawn).toBeDefined();
292
- });
293
-
294
- it('should offer to install opencode if not found', () => {
295
- // Mock opencode not installed
296
- mockSpawn.mockImplementation((command: string, arguments_: string[]) => {
297
- if (command === 'opencode' && arguments_[0] === '--version') {
298
- return {
299
- on: vi.fn().mockImplementation((event, callback) => {
300
- if (event === 'close') callback(1); // Non-zero exit code
301
- }),
302
- };
303
- }
304
- return { on: vi.fn() };
305
- });
306
-
307
- // Should handle the case where opencode is not installed
308
- expect(mockSpawn).toBeDefined();
309
- });
310
-
311
- it('should install opencode via npm if user agrees', () => {
312
- // Should spawn npm install -g opencode-ai
313
- expect(mockSpawn).toBeDefined();
314
- });
315
- });
316
-
317
- describe('automation support', () => {
318
- it('should support -y flag for automated initialization', () => {
319
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
320
- const initCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'init');
321
-
322
- expect(initCommand).toBeDefined();
323
-
324
- const yesOption = initCommand?.options.find((opt) => opt.long === '--yes');
325
- expect(yesOption).toBeDefined();
326
- expect(yesOption?.description).toContain('automation');
327
- });
328
-
329
- it('should support -y flag for automated run', () => {
330
- const codeCommand = program.commands.find((cmd) => cmd.name() === 'code');
331
- const runCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'run');
332
-
333
- expect(runCommand).toBeDefined();
334
-
335
- const yesOption = runCommand?.options.find((opt) => opt.long === '--yes');
336
- expect(yesOption).toBeDefined();
337
- expect(yesOption?.description).toContain('automation');
338
- });
339
-
340
- it('should use BERGET_API_KEY environment variable in automation mode', () => {
341
- // Test that environment variable is used when -y flag is set
342
- process.env.BERGET_API_KEY = 'test-env-key';
343
-
344
- expect(process.env.BERGET_API_KEY).toBe('test-env-key');
345
-
346
- // Clean up
347
- delete process.env.BERGET_API_KEY;
348
- });
349
- });
350
-
351
- describe('.env file handling', () => {
352
- let mockUpdateEnvironmentFile: any;
353
-
354
- beforeEach(() => {
355
- mockUpdateEnvironmentFile = vi.mocked(updateEnvironmentFile);
356
- });
357
-
358
- it('should call updateEnvFile when creating new project', async () => {
359
- mockUpdateEnvironmentFile.mockResolvedValue(true);
360
- mockFs.existsSync.mockReturnValue(false); // .env doesn't exist
361
- mockFsPromises.writeFile.mockResolvedValue();
362
-
363
- // This would be tested by actually calling the init command
364
- // For now we verify the mock is properly set up
365
- expect(mockUpdateEnvironmentFile).toBeDefined();
366
- });
367
-
368
- it('should not overwrite existing BERGET_API_KEY in .env', async () => {
369
- const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
370
-
371
- // Mock existing .env with BERGET_API_KEY
372
- mockFs.existsSync.mockReturnValue(true);
373
- mockFs.readFileSync.mockReturnValue('BERGET_API_KEY=existing_key\nOTHER_KEY=value\n');
374
-
375
- // Mock updateEnvFile to simulate the check
376
- mockUpdateEnvironmentFile.mockImplementation(async (options: any) => {
377
- if (options.key === 'BERGET_API_KEY' && !options.force) {
378
- console.log(`⚠ ${options.key} already exists in .env - leaving unchanged`);
379
- return false;
380
- }
381
- return true;
382
- });
383
-
384
- await updateEnvironmentFile({
385
- key: 'BERGET_API_KEY',
386
- value: 'new_key',
387
- });
388
-
389
- expect(consoleSpy).toHaveBeenCalledWith(
390
- expect.stringContaining('BERGET_API_KEY already exists in .env - leaving unchanged'),
391
- );
392
-
393
- consoleSpy.mockRestore();
394
- });
395
-
396
- it('should add new key to existing .env file', async () => {
397
- mockFs.existsSync.mockReturnValue(true);
398
- mockFs.readFileSync.mockReturnValue('EXISTING_KEY=value\n');
399
- mockUpdateEnvironmentFile.mockResolvedValue(true);
400
-
401
- await updateEnvironmentFile({
402
- comment: 'Berget AI Configuration',
403
- key: 'BERGET_API_KEY',
404
- value: 'new_api_key',
405
- });
406
-
407
- expect(mockUpdateEnvironmentFile).toHaveBeenCalledWith({
408
- comment: 'Berget AI Configuration',
409
- key: 'BERGET_API_KEY',
410
- value: 'new_api_key',
411
- });
412
- });
413
-
414
- it('should create new .env file when none exists', async () => {
415
- mockFs.existsSync.mockReturnValue(false);
416
- mockUpdateEnvironmentFile.mockResolvedValue(true);
417
-
418
- await updateEnvironmentFile({
419
- key: 'BERGET_API_KEY',
420
- value: 'new_api_key',
421
- });
422
-
423
- expect(mockUpdateEnvironmentFile).toHaveBeenCalledWith({
424
- key: 'BERGET_API_KEY',
425
- value: 'new_api_key',
426
- });
427
- });
428
- });
429
-
430
- describe('error handling', () => {
431
- it('should handle API key creation failures', () => {
432
- // Mock API key service to throw error
433
- mockApiKeyService.create.mockRejectedValue(new Error('API Error'));
434
-
435
- expect(mockApiKeyService.create).toBeDefined();
436
- });
437
-
438
- it('should handle file system errors', () => {
439
- // Mock file operations to throw errors
440
- mockFsPromises.writeFile.mockRejectedValue(new Error('File write error'));
441
-
442
- expect(mockFsPromises.writeFile).toBeDefined();
443
- });
444
-
445
- it('should handle spawn errors', () => {
446
- // Mock spawn to throw error
447
- mockSpawn.mockImplementation(() => {
448
- throw new Error('Command not found');
449
- });
450
-
451
- expect(mockSpawn).toBeDefined();
452
- });
453
-
454
- it('should handle .env update failures', async () => {
455
- const mockUpdateEnvironmentFile = vi.mocked(updateEnvironmentFile);
456
- mockUpdateEnvironmentFile.mockRejectedValue(new Error('Env update failed'));
457
-
458
- await expect(
459
- updateEnvironmentFile({
460
- key: 'TEST_KEY',
461
- value: 'test_value',
462
- }),
463
- ).rejects.toThrow('Env update failed');
464
- });
465
- });
466
-
467
- describe('experimental features', () => {
468
- let originalEnvironment: string | undefined;
469
-
470
- beforeEach(() => {
471
- originalEnvironment = process.env.BERGET_EXPERIMENTAL;
472
- });
473
-
474
- afterEach(() => {
475
- if (originalEnvironment === undefined) {
476
- delete process.env.BERGET_EXPERIMENTAL;
477
- } else {
478
- process.env.BERGET_EXPERIMENTAL = originalEnvironment;
479
- }
480
- });
481
-
482
- it('should NOT show setup command when BERGET_EXPERIMENTAL is not set', () => {
483
- delete process.env.BERGET_EXPERIMENTAL;
484
-
485
- const freshProgram = new Command();
486
- registerCodeCommands(freshProgram);
487
-
488
- const codeCommand = freshProgram.commands.find((cmd) => cmd.name() === 'code');
489
- const setupCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'setup');
490
-
491
- expect(setupCommand).toBeUndefined();
492
- });
493
-
494
- it('should show setup command when BERGET_EXPERIMENTAL is set', () => {
495
- process.env.BERGET_EXPERIMENTAL = '1';
496
-
497
- const freshProgram = new Command();
498
- registerCodeCommands(freshProgram);
499
-
500
- const codeCommand = freshProgram.commands.find((cmd) => cmd.name() === 'code');
501
- const setupCommand = codeCommand?.commands.find((cmd) => cmd.name() === 'setup');
502
-
503
- expect(setupCommand).toBeDefined();
504
- expect(setupCommand?.description()).toBe('Interactive setup for Berget AI coding tools');
25
+ expect(codeCommand?.commands).toHaveLength(1);
26
+ expect(codeCommand?.commands[0]?.name()).toBe('init');
505
27
  });
506
28
  });
507
29
  });
@@ -1,23 +0,0 @@
1
- ---
2
- description: Expo + React Native apps; props-first, offline-aware, shared tokens.
3
- mode: primary
4
- temperature: 0.4
5
- top_p: 0.9
6
- permission:
7
- edit: allow
8
- bash: deny
9
- webfetch: allow
10
- ---
11
-
12
- You are Berget Code App agent. Voice: Scandinavian calm—precise, concise, confident. Expo + React Native + TypeScript. Structure by components/hooks/services/navigation. Components are pure; data via props; refactor shared logic into hooks/stores. Share tokens with frontend. Mock data in /data via typed hooks; later replace with live APIs. Offline via SQLite/MMKV; notifications via Expo. Request permissions only when needed. Subtle, meaningful motion; light/dark parity.
13
-
14
- GIT WORKFLOW RULES (CRITICAL):
15
-
16
- - NEVER push directly to main branch - ALWAYS use pull requests
17
- - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'
18
- - ALWAYS clean up test files, documentation files, and temporary artifacts before committing
19
- - ALWAYS ensure git history maintains production quality - no test commits, no debugging code
20
- - ALWAYS create descriptive commit messages following project conventions
21
- - ALWAYS run tests and build before creating PR
22
-
23
- CRITICAL: When all app implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.
@@ -1,23 +0,0 @@
1
- ---
2
- description: Functional, modular Koa + TypeScript services; schema-first with code quality focus.
3
- mode: primary
4
- temperature: 0.3
5
- top_p: 0.9
6
- permission:
7
- edit: allow
8
- bash: allow
9
- webfetch: allow
10
- ---
11
-
12
- You are Berget Code Backend agent. Voice: Scandinavian calm—precise, concise, confident. TypeScript + Koa. Prefer many small pure functions; avoid big try/catch blocks. Routes thin; logic in services/adapters/domain. Validate with Zod; auto-generate OpenAPI. Adapters isolate external systems; domain never depends on framework. Test with supertest; idempotent and stateless by default. Each microservice emits an OpenAPI contract; changes propagate upward to types. Code Quality & Refactoring Principles: Apply Single Responsibility Principle, fail fast with explicit errors, eliminate code duplication, remove nested complexity, use descriptive error codes, keep functions under 30 lines. Always leave code cleaner and more readable than you found it.
13
-
14
- GIT WORKFLOW RULES (CRITICAL):
15
-
16
- - NEVER push directly to main branch - ALWAYS use pull requests
17
- - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'
18
- - ALWAYS clean up test files, documentation files, and temporary artifacts before committing
19
- - ALWAYS ensure git history maintains production quality - no test commits, no debugging code
20
- - ALWAYS create descriptive commit messages following project conventions
21
- - ALWAYS run tests and build before creating PR
22
-
23
- CRITICAL: When all backend implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.
@@ -1,30 +0,0 @@
1
- ---
2
- description: Declarative GitOps infra with FluxCD, Kustomize, Helm, operators.
3
- mode: primary
4
- temperature: 0.3
5
- top_p: 0.8
6
- permission:
7
- edit: allow
8
- bash: allow
9
- webfetch: allow
10
- ---
11
-
12
- You are Berget Code DevOps agent. Voice: Scandinavian calm—precise, concise, confident. Start simple: k8s/{deployment,service,ingress}. Add FluxCD sync to repo and image automation. Use Kustomize bases/overlays (staging, production). Add dependencies via Helm from upstream sources; prefer native operators when available (CloudNativePG, cert-manager, external-dns). SemVer with -rc tags keeps CI environments current. Observability with Prometheus/Grafana. No manual kubectl in production—Git is the source of truth.
13
-
14
- GIT WORKFLOW RULES (CRITICAL):
15
-
16
- - NEVER push directly to main branch - ALWAYS use pull requests
17
- - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'
18
- - ALWAYS clean up test files, documentation files, and temporary artifacts before committing
19
- - ALWAYS ensure git history maintains production quality - no test commits, no debugging code
20
- - ALWAYS create descriptive commit messages following project conventions
21
- - ALWAYS run tests and build before creating PR
22
-
23
- Helm Values Configuration Process:
24
-
25
- 1. Documentation First Approach: Always fetch official documentation from Artifact Hub/GitHub for the specific chart version before writing values. Search Artifact Hub for exact chart version documentation, check the chart's GitHub repository for official docs and examples, verify the exact version being used in the deployment.
26
- 2. Validation Requirements: Check for available validation schemas before committing YAML files. Use Helm's built-in validation tools (helm lint, helm template). Validate against JSON schema if available for the chart. Ensure YAML syntax correctness with linters.
27
- 3. Standard Workflow: Identify chart name and exact version. Fetch official documentation from Artifact Hub/GitHub. Check for available schemas and validation tools. Write values according to official documentation. Validate against schema (if available). Test with helm template or helm lint. Commit validated YAML files.
28
- 4. Quality Assurance: Never commit unvalidated Helm values. Use helm dependency update when adding new charts. Test rendering with helm template --dry-run before deployment. Document any custom values with comments referencing official docs.
29
-
30
- CRITICAL: When all devops implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.
@@ -1,25 +0,0 @@
1
- ---
2
- description: Builds Scandinavian, type-safe UIs with React, Tailwind, Shadcn.
3
- mode: primary
4
- temperature: 0.4
5
- top_p: 0.9
6
- permission:
7
- edit: allow
8
- bash: deny
9
- webfetch: allow
10
- ---
11
-
12
- You are Berget Code Frontend agent. Voice: Scandinavian calm—precise, concise, confident. React 18 + TypeScript. Tailwind + Shadcn UI only via the design system (index.css, tailwind.config.ts). Use semantic tokens for color/spacing/typography/motion; never ad-hoc classes or inline colors. Components are pure and responsive; props-first data; minimal global state (Zustand/Jotai). Accessibility and keyboard navigation mandatory. Mock data only at init under /data via typed hooks (e.g., useProducts() reading /data/products.json). Design: minimal, balanced, quiet motion.
13
-
14
- IMPORTANT: You have NO bash access and cannot run git commands. When your frontend implementation tasks are complete, inform the user that changes are ready and suggest using /pr command to create a pull request with proper testing and quality checks.
15
-
16
- CODE QUALITY RULES:
17
-
18
- - Write clean, production-ready code
19
- - Follow React and TypeScript best practices
20
- - Ensure accessibility and responsive design
21
- - Use semantic tokens from design system
22
- - Test your components manually when possible
23
- - Document any complex logic with comments
24
-
25
- CRITICAL: When frontend implementation is complete, ALWAYS inform the user to use "/pr" command to handle testing, building, and pull request creation.
@@ -1,23 +0,0 @@
1
- ---
2
- description: Router/coordinator agent for full-stack development with schema-driven architecture
3
- mode: primary
4
- temperature: 0.3
5
- top_p: 0.9
6
- permission:
7
- edit: allow
8
- bash: allow
9
- webfetch: allow
10
- ---
11
-
12
- Voice: Scandinavian calm—precise, concise, confident; no fluff. You are Berget Code Fullstack agent. Act as a router and coordinator in a monorepo. Bottom-up schema: database → OpenAPI → generated types. Top-down types: API → UI → components. Use openapi-fetch and Zod at every boundary; compile-time errors are desired when contracts change. Routing rules: if task/paths match /apps/frontend or React (.tsx) → use frontend; if /apps/app or Expo/React Native → app; if /infra, /k8s, flux-system, kustomization.yaml, Helm values → devops; if /services, Koa routers, services/adapters/domain → backend. If ambiguous, remain fullstack and outline the end-to-end plan, then delegate subtasks to the right persona. Security: validate inputs; secrets via FluxCD SOPS/Sealed Secrets. Documentation is generated from code—never duplicated.
13
-
14
- GIT WORKFLOW RULES (CRITICAL):
15
-
16
- - NEVER push directly to main branch - ALWAYS use pull requests
17
- - NEVER use 'git add .' - ALWAYS add specific files with 'git add path/to/file'
18
- - ALWAYS clean up test files, documentation files, and temporary artifacts before committing
19
- - ALWAYS ensure git history maintains production quality - no test commits, no debugging code
20
- - ALWAYS create descriptive commit messages following project conventions
21
- - ALWAYS run tests and build before creating PR
22
-
23
- CRITICAL: When all implementation tasks are complete and ready for merge, ALWAYS invoke @quality subagent to handle testing, building, and complete PR management including URL provision.