@grunnverk/kilde 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
- package/.github/pull_request_template.md +48 -0
- package/.github/workflows/deploy-docs.yml +59 -0
- package/.github/workflows/npm-publish.yml +48 -0
- package/.github/workflows/test.yml +48 -0
- package/CHANGELOG.md +92 -0
- package/CONTRIBUTING.md +438 -0
- package/LICENSE +190 -0
- package/PROJECT_SUMMARY.md +318 -0
- package/README.md +444 -0
- package/RELEASE_CHECKLIST.md +182 -0
- package/dist/application.js +166 -0
- package/dist/application.js.map +1 -0
- package/dist/commands/release.js +326 -0
- package/dist/commands/release.js.map +1 -0
- package/dist/constants.js +122 -0
- package/dist/constants.js.map +1 -0
- package/dist/logging.js +176 -0
- package/dist/logging.js.map +1 -0
- package/dist/main.js +24 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp-server.js +17467 -0
- package/dist/mcp-server.js.map +7 -0
- package/dist/utils/config.js +89 -0
- package/dist/utils/config.js.map +1 -0
- package/docs/AI_GUIDE.md +618 -0
- package/eslint.config.mjs +85 -0
- package/guide/architecture.md +776 -0
- package/guide/commands.md +580 -0
- package/guide/configuration.md +779 -0
- package/guide/mcp-integration.md +708 -0
- package/guide/overview.md +225 -0
- package/package.json +91 -0
- package/scripts/build-mcp.js +115 -0
- package/scripts/test-mcp-compliance.js +254 -0
- package/src/application.ts +246 -0
- package/src/commands/release.ts +450 -0
- package/src/constants.ts +162 -0
- package/src/logging.ts +210 -0
- package/src/main.ts +25 -0
- package/src/mcp/prompts/index.ts +98 -0
- package/src/mcp/resources.ts +121 -0
- package/src/mcp/server.ts +195 -0
- package/src/mcp/tools.ts +219 -0
- package/src/types.ts +131 -0
- package/src/utils/config.ts +181 -0
- package/tests/application.test.ts +114 -0
- package/tests/commands/commit.test.ts +248 -0
- package/tests/commands/release.test.ts +325 -0
- package/tests/constants.test.ts +118 -0
- package/tests/logging.test.ts +142 -0
- package/tests/mcp/prompts/index.test.ts +202 -0
- package/tests/mcp/resources.test.ts +166 -0
- package/tests/mcp/tools.test.ts +211 -0
- package/tests/utils/config.test.ts +212 -0
- package/tsconfig.json +32 -0
- package/vite.config.ts +107 -0
- package/vitest.config.ts +40 -0
- package/website/index.html +14 -0
- package/website/src/App.css +142 -0
- package/website/src/App.tsx +34 -0
- package/website/src/components/Commands.tsx +182 -0
- package/website/src/components/Configuration.tsx +214 -0
- package/website/src/components/Examples.tsx +234 -0
- package/website/src/components/Footer.css +99 -0
- package/website/src/components/Footer.tsx +93 -0
- package/website/src/components/GettingStarted.tsx +94 -0
- package/website/src/components/Hero.css +95 -0
- package/website/src/components/Hero.tsx +50 -0
- package/website/src/components/Navigation.css +102 -0
- package/website/src/components/Navigation.tsx +57 -0
- package/website/src/index.css +36 -0
- package/website/src/main.tsx +10 -0
- package/website/vite.config.ts +12 -0
|
@@ -0,0 +1,776 @@
|
|
|
1
|
+
# Architecture Guide
|
|
2
|
+
|
|
3
|
+
Technical overview of Kilde's implementation, design decisions, and internal architecture.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Kilde is a TypeScript-based CLI tool and MCP server built on the @grunnverk package ecosystem. It follows a modular architecture with clear separation of concerns and minimal dependencies.
|
|
8
|
+
|
|
9
|
+
## System Architecture
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────┐
|
|
13
|
+
│ User Interface │
|
|
14
|
+
├─────────────────────────────────────────────────────────┤
|
|
15
|
+
│ CLI (Commander.js) │ MCP Server (stdio transport) │
|
|
16
|
+
├─────────────────────────────────────────────────────────┤
|
|
17
|
+
│ Application Layer │
|
|
18
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
19
|
+
│ │ Commands │ │ MCP Tools │ │ MCP │ │
|
|
20
|
+
│ │ │ │ │ │ Resources │ │
|
|
21
|
+
│ │ • commit │ │ • kilde_ │ │ │ │
|
|
22
|
+
│ │ • release │ │ commit │ │ • config │ │
|
|
23
|
+
│ │ │ │ • kilde_ │ │ • status │ │
|
|
24
|
+
│ │ │ │ release │ │ • workspace │ │
|
|
25
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
26
|
+
├─────────────────────────────────────────────────────────┤
|
|
27
|
+
│ Service Layer │
|
|
28
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
29
|
+
│ │ AI Service │ │ Git Tools │ │ Config │ │
|
|
30
|
+
│ │ │ │ │ │ │ │
|
|
31
|
+
│ │ • OpenAI │ │ • git ops │ │ • loading │ │
|
|
32
|
+
│ │ • Anthropic │ │ • diff │ │ • merging │ │
|
|
33
|
+
│ │ • formatting │ │ • log │ │ • validation │ │
|
|
34
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
35
|
+
├─────────────────────────────────────────────────────────┤
|
|
36
|
+
│ Core Infrastructure │
|
|
37
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
38
|
+
│ │ Logging │ │ Types │ │ Constants │ │
|
|
39
|
+
│ │ │ │ │ │ │ │
|
|
40
|
+
│ │ • Winston │ │ • Config │ │ • defaults │ │
|
|
41
|
+
│ │ • transports │ │ • Command │ │ • paths │ │
|
|
42
|
+
│ │ • formatters │ │ • MCP types │ │ • messages │ │
|
|
43
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
44
|
+
└─────────────────────────────────────────────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Project Structure
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
kilde/
|
|
51
|
+
├── src/
|
|
52
|
+
│ ├── main.ts # CLI entry point
|
|
53
|
+
│ ├── application.ts # CLI application setup
|
|
54
|
+
│ ├── constants.ts # Constants and defaults
|
|
55
|
+
│ ├── logging.ts # Logging configuration
|
|
56
|
+
│ ├── types.ts # TypeScript type definitions
|
|
57
|
+
│ ├── commands/
|
|
58
|
+
│ │ └── release.ts # Release notes command
|
|
59
|
+
│ ├── mcp/
|
|
60
|
+
│ │ ├── server.ts # MCP server implementation
|
|
61
|
+
│ │ ├── tools.ts # MCP tool handlers
|
|
62
|
+
│ │ ├── resources.ts # MCP resource handlers
|
|
63
|
+
│ │ └── prompts/
|
|
64
|
+
│ │ └── index.ts # MCP prompt workflows
|
|
65
|
+
│ └── utils/
|
|
66
|
+
│ └── config.ts # Configuration utilities
|
|
67
|
+
├── tests/ # Test suites
|
|
68
|
+
├── docs/ # Documentation
|
|
69
|
+
└── guide/ # User guides
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Core Components
|
|
73
|
+
|
|
74
|
+
### CLI Application (`src/application.ts`)
|
|
75
|
+
|
|
76
|
+
Entry point for the command-line interface.
|
|
77
|
+
|
|
78
|
+
**Responsibilities**:
|
|
79
|
+
- Parse command-line arguments with Commander.js
|
|
80
|
+
- Route commands to appropriate handlers
|
|
81
|
+
- Merge configuration from multiple sources
|
|
82
|
+
- Initialize logging based on flags
|
|
83
|
+
- Handle global flags (--debug, --config, --version)
|
|
84
|
+
|
|
85
|
+
**Key Code**:
|
|
86
|
+
```typescript
|
|
87
|
+
export async function createApplication(): Promise<Command> {
|
|
88
|
+
const program = new Command();
|
|
89
|
+
|
|
90
|
+
program
|
|
91
|
+
.name('kilde')
|
|
92
|
+
.description('Universal Git Automation Tool')
|
|
93
|
+
.version(VERSION);
|
|
94
|
+
|
|
95
|
+
// Global flags
|
|
96
|
+
program.option('--debug', 'Enable debug logging');
|
|
97
|
+
program.option('--config <path>', 'Path to config file');
|
|
98
|
+
|
|
99
|
+
// Commands
|
|
100
|
+
program
|
|
101
|
+
.command('commit')
|
|
102
|
+
.description('Generate and create commits')
|
|
103
|
+
.action(async (options) => {
|
|
104
|
+
const config = await loadConfig(options);
|
|
105
|
+
await commitCommand(config);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return program;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Design Decisions**:
|
|
113
|
+
- Commander.js for consistent CLI patterns
|
|
114
|
+
- Lazy-load commands for faster startup
|
|
115
|
+
- Early logging initialization for debugging
|
|
116
|
+
- Node.js version check at startup (requires 24+)
|
|
117
|
+
|
|
118
|
+
### Configuration System (`src/utils/config.ts`)
|
|
119
|
+
|
|
120
|
+
Flexible configuration loading and merging.
|
|
121
|
+
|
|
122
|
+
**Responsibilities**:
|
|
123
|
+
- Search multiple locations for config files
|
|
124
|
+
- Parse YAML and JSON formats
|
|
125
|
+
- Deep merge with defaults
|
|
126
|
+
- Validate configuration schema
|
|
127
|
+
- Apply environment variable overrides
|
|
128
|
+
|
|
129
|
+
**Search Order**:
|
|
130
|
+
1. CLI `--config` flag
|
|
131
|
+
2. `.kilde/config.yaml` (project)
|
|
132
|
+
3. `.kilderc.yaml` (project root)
|
|
133
|
+
4. `~/.kilde/config.yaml` (user home)
|
|
134
|
+
|
|
135
|
+
**Key Code**:
|
|
136
|
+
```typescript
|
|
137
|
+
export async function loadConfig(cliOptions: any): Promise<Config> {
|
|
138
|
+
const configs: Config[] = [];
|
|
139
|
+
|
|
140
|
+
// Load from all locations
|
|
141
|
+
for (const location of CONFIG_LOCATIONS) {
|
|
142
|
+
const config = await loadConfigFile(location);
|
|
143
|
+
if (config) configs.push(config);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Merge: defaults < user home < project < CLI
|
|
147
|
+
return deepMerge(KILDE_DEFAULTS, ...configs, cliOptions);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Design Decisions**:
|
|
152
|
+
- YAML as primary format (more human-readable)
|
|
153
|
+
- Deep merge allows partial overrides
|
|
154
|
+
- No validation errors for unknown fields (forward compatibility)
|
|
155
|
+
- Config from @grunnverk/core provides base types
|
|
156
|
+
|
|
157
|
+
### Logging System (`src/logging.ts`)
|
|
158
|
+
|
|
159
|
+
Structured logging with Winston.
|
|
160
|
+
|
|
161
|
+
**Responsibilities**:
|
|
162
|
+
- Initialize Winston loggers
|
|
163
|
+
- Configure transports (console, file)
|
|
164
|
+
- Format log messages
|
|
165
|
+
- Handle debug mode
|
|
166
|
+
- Redact sensitive information
|
|
167
|
+
|
|
168
|
+
**Log Levels**:
|
|
169
|
+
- `error`: Critical errors
|
|
170
|
+
- `warn`: Warnings and recoverable errors
|
|
171
|
+
- `info`: Informational messages (default)
|
|
172
|
+
- `debug`: Detailed execution information
|
|
173
|
+
|
|
174
|
+
**Key Code**:
|
|
175
|
+
```typescript
|
|
176
|
+
export function createLogger(options: LoggerOptions): Logger {
|
|
177
|
+
return winston.createLogger({
|
|
178
|
+
level: options.debug ? 'debug' : 'info',
|
|
179
|
+
format: winston.format.combine(
|
|
180
|
+
winston.format.timestamp(),
|
|
181
|
+
winston.format.json()
|
|
182
|
+
),
|
|
183
|
+
transports: [
|
|
184
|
+
new winston.transports.Console(),
|
|
185
|
+
new winston.transports.File({
|
|
186
|
+
filename: path.join(options.logDir, 'kilde.log')
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Design Decisions**:
|
|
194
|
+
- Winston for production-ready logging
|
|
195
|
+
- JSON format for machine parsing
|
|
196
|
+
- File logs for debugging
|
|
197
|
+
- Sensitive data redaction (API keys, tokens)
|
|
198
|
+
|
|
199
|
+
### Commit Command
|
|
200
|
+
|
|
201
|
+
Delegates to `@grunnverk/commands-git` for implementation.
|
|
202
|
+
|
|
203
|
+
**Flow**:
|
|
204
|
+
1. Load configuration
|
|
205
|
+
2. Check git status
|
|
206
|
+
3. Stage changes if `--add`
|
|
207
|
+
4. Generate diff
|
|
208
|
+
5. Call AI service for message
|
|
209
|
+
6. Review in interactive mode (optional)
|
|
210
|
+
7. Create commit
|
|
211
|
+
8. Push if `--push`
|
|
212
|
+
|
|
213
|
+
**Integration**:
|
|
214
|
+
```typescript
|
|
215
|
+
import { commitCommand } from '@grunnverk/commands-git';
|
|
216
|
+
|
|
217
|
+
// Kilde delegates to shared implementation
|
|
218
|
+
await commitCommand(config);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Design Decisions**:
|
|
222
|
+
- Reuse @grunnverk/commands-git (no duplication)
|
|
223
|
+
- Kilde provides configuration layer only
|
|
224
|
+
- All logic in shared package
|
|
225
|
+
|
|
226
|
+
### Release Command (`src/commands/release.ts`)
|
|
227
|
+
|
|
228
|
+
Pure git-based release notes generation.
|
|
229
|
+
|
|
230
|
+
**Responsibilities**:
|
|
231
|
+
- Determine tag range (from/to)
|
|
232
|
+
- Fetch commit history between tags
|
|
233
|
+
- Parse conventional commits
|
|
234
|
+
- Group by type/scope
|
|
235
|
+
- Format as markdown
|
|
236
|
+
- Generate with AI assistance
|
|
237
|
+
|
|
238
|
+
**Flow**:
|
|
239
|
+
1. Determine `from` and `to` references
|
|
240
|
+
2. Get commits: `git log from..to`
|
|
241
|
+
3. Parse commit messages
|
|
242
|
+
4. Group and categorize
|
|
243
|
+
5. Generate release notes with AI
|
|
244
|
+
6. Review (interactive) or save (output file)
|
|
245
|
+
|
|
246
|
+
**Key Code**:
|
|
247
|
+
```typescript
|
|
248
|
+
export async function releaseCommand(config: Config): Promise<void> {
|
|
249
|
+
const from = config.release?.from ?? await getLastTag();
|
|
250
|
+
const to = config.release?.to ?? 'HEAD';
|
|
251
|
+
|
|
252
|
+
const commits = await getCommitsBetween(from, to);
|
|
253
|
+
const grouped = groupCommits(commits);
|
|
254
|
+
const notes = await generateReleaseNotes(grouped, config);
|
|
255
|
+
|
|
256
|
+
if (config.release?.output) {
|
|
257
|
+
await fs.writeFile(config.release.output, notes);
|
|
258
|
+
} else {
|
|
259
|
+
console.log(notes);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Design Decisions**:
|
|
265
|
+
- Pure git (no GitHub API)
|
|
266
|
+
- Works with any git host
|
|
267
|
+
- AI-enhanced formatting
|
|
268
|
+
- Conventional commit parsing
|
|
269
|
+
- Flexible grouping strategies
|
|
270
|
+
|
|
271
|
+
### MCP Server (`src/mcp/server.ts`)
|
|
272
|
+
|
|
273
|
+
Model Context Protocol server implementation.
|
|
274
|
+
|
|
275
|
+
**Responsibilities**:
|
|
276
|
+
- Implement MCP protocol via SDK
|
|
277
|
+
- Expose tools, resources, prompts
|
|
278
|
+
- Handle stdio transport
|
|
279
|
+
- Route requests to handlers
|
|
280
|
+
- Manage server lifecycle
|
|
281
|
+
|
|
282
|
+
**Key Code**:
|
|
283
|
+
```typescript
|
|
284
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
285
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
286
|
+
|
|
287
|
+
const server = new Server(
|
|
288
|
+
{
|
|
289
|
+
name: 'kilde',
|
|
290
|
+
version: '0.1.0'
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
capabilities: {
|
|
294
|
+
tools: {},
|
|
295
|
+
resources: {},
|
|
296
|
+
prompts: {}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
// Register handlers
|
|
302
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
303
|
+
return { tools: AVAILABLE_TOOLS };
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
307
|
+
return await executeTool(request.params.name, request.params.arguments);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Start with stdio transport
|
|
311
|
+
const transport = new StdioServerTransport();
|
|
312
|
+
await server.connect(transport);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**Design Decisions**:
|
|
316
|
+
- MCP SDK for protocol compliance
|
|
317
|
+
- stdio transport (standard for MCP)
|
|
318
|
+
- Delegate to command implementations
|
|
319
|
+
- Type-safe with literal types (`'text' as const`)
|
|
320
|
+
|
|
321
|
+
### MCP Tools (`src/mcp/tools.ts`)
|
|
322
|
+
|
|
323
|
+
Tool execution handlers.
|
|
324
|
+
|
|
325
|
+
**Available Tools**:
|
|
326
|
+
- `kilde_commit`: Execute commit command via MCP
|
|
327
|
+
- `kilde_release`: Execute release command via MCP
|
|
328
|
+
|
|
329
|
+
**Key Code**:
|
|
330
|
+
```typescript
|
|
331
|
+
export async function executeTool(
|
|
332
|
+
name: string,
|
|
333
|
+
args: Record<string, any>,
|
|
334
|
+
context: ToolContext
|
|
335
|
+
): Promise<ToolResult> {
|
|
336
|
+
if (name === 'kilde_commit') {
|
|
337
|
+
const config = buildConfig(args, context);
|
|
338
|
+
const result = await commitCommand(config);
|
|
339
|
+
return {
|
|
340
|
+
content: [{
|
|
341
|
+
type: 'text' as const,
|
|
342
|
+
text: formatCommitResult(result)
|
|
343
|
+
}]
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
// ...
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Design Decisions**:
|
|
351
|
+
- Reuse command implementations
|
|
352
|
+
- Build Config from MCP parameters
|
|
353
|
+
- Return formatted results
|
|
354
|
+
- Handle errors gracefully
|
|
355
|
+
|
|
356
|
+
### MCP Resources (`src/mcp/resources.ts`)
|
|
357
|
+
|
|
358
|
+
Read-only resource providers.
|
|
359
|
+
|
|
360
|
+
**Available Resources**:
|
|
361
|
+
- `kilde://config`: Current configuration
|
|
362
|
+
- `kilde://status`: Git repository status
|
|
363
|
+
- `kilde://workspace`: Workspace information
|
|
364
|
+
|
|
365
|
+
**Key Code**:
|
|
366
|
+
```typescript
|
|
367
|
+
export async function readResource(uri: string): Promise<ResourceContents> {
|
|
368
|
+
if (uri === 'kilde://config') {
|
|
369
|
+
const config = await loadConfig({});
|
|
370
|
+
return {
|
|
371
|
+
contents: [{
|
|
372
|
+
uri,
|
|
373
|
+
mimeType: 'application/json',
|
|
374
|
+
text: JSON.stringify(config, null, 2)
|
|
375
|
+
}]
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
// ...
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Design Decisions**:
|
|
383
|
+
- URI-based addressing
|
|
384
|
+
- JSON for structured data
|
|
385
|
+
- Real-time data (no caching)
|
|
386
|
+
- Read-only access
|
|
387
|
+
|
|
388
|
+
### MCP Prompts (`src/mcp/prompts/index.ts`)
|
|
389
|
+
|
|
390
|
+
Predefined workflow prompts.
|
|
391
|
+
|
|
392
|
+
**Available Prompts**:
|
|
393
|
+
- `commit-workflow`: Guided commit creation
|
|
394
|
+
- `release-workflow`: Guided release creation
|
|
395
|
+
|
|
396
|
+
**Key Code**:
|
|
397
|
+
```typescript
|
|
398
|
+
export async function getPrompt(
|
|
399
|
+
name: string,
|
|
400
|
+
args?: Record<string, string>
|
|
401
|
+
): Promise<GetPromptResult> {
|
|
402
|
+
if (name === 'commit-workflow') {
|
|
403
|
+
return {
|
|
404
|
+
messages: [{
|
|
405
|
+
role: 'user' as const,
|
|
406
|
+
content: {
|
|
407
|
+
type: 'text' as const,
|
|
408
|
+
text: buildCommitWorkflowPrompt(args)
|
|
409
|
+
}
|
|
410
|
+
}]
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
// ...
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Design Decisions**:
|
|
418
|
+
- Template-based prompts
|
|
419
|
+
- Parameterized workflows
|
|
420
|
+
- LLM-friendly formatting
|
|
421
|
+
- Step-by-step guidance
|
|
422
|
+
|
|
423
|
+
## Package Dependencies
|
|
424
|
+
|
|
425
|
+
### Core Dependencies
|
|
426
|
+
|
|
427
|
+
#### `@grunnverk/commands-git`
|
|
428
|
+
Provides `commitCommand` implementation.
|
|
429
|
+
|
|
430
|
+
**Why**: Shared commit logic across tools
|
|
431
|
+
|
|
432
|
+
#### `@grunnverk/core`
|
|
433
|
+
Core types (Config, ReleaseConfig, etc.) and utilities.
|
|
434
|
+
|
|
435
|
+
**Why**: Consistent types across ecosystem
|
|
436
|
+
|
|
437
|
+
#### `@grunnverk/ai-service`
|
|
438
|
+
AI model integration (OpenAI, Anthropic).
|
|
439
|
+
|
|
440
|
+
**Why**: Shared AI client with rate limiting, retries
|
|
441
|
+
|
|
442
|
+
#### `@grunnverk/git-tools`
|
|
443
|
+
Git operations (status, diff, log, etc.).
|
|
444
|
+
|
|
445
|
+
**Why**: Consistent git command execution
|
|
446
|
+
|
|
447
|
+
#### `@grunnverk/shared`
|
|
448
|
+
Shared utilities (logging, formatting, etc.).
|
|
449
|
+
|
|
450
|
+
**Why**: Common functionality across packages
|
|
451
|
+
|
|
452
|
+
#### `@modelcontextprotocol/sdk`
|
|
453
|
+
MCP protocol implementation.
|
|
454
|
+
|
|
455
|
+
**Why**: Standard MCP server implementation
|
|
456
|
+
|
|
457
|
+
#### `@riotprompt/riotprompt`
|
|
458
|
+
Prompt formatting for LLMs.
|
|
459
|
+
|
|
460
|
+
**Why**: Structured prompt generation
|
|
461
|
+
|
|
462
|
+
#### `commander`
|
|
463
|
+
CLI argument parsing.
|
|
464
|
+
|
|
465
|
+
**Why**: Industry-standard CLI framework
|
|
466
|
+
|
|
467
|
+
#### `winston`
|
|
468
|
+
Logging infrastructure.
|
|
469
|
+
|
|
470
|
+
**Why**: Production-ready logging with transports
|
|
471
|
+
|
|
472
|
+
#### `js-yaml`
|
|
473
|
+
YAML parsing for config files.
|
|
474
|
+
|
|
475
|
+
**Why**: Human-friendly config format
|
|
476
|
+
|
|
477
|
+
### Development Dependencies
|
|
478
|
+
|
|
479
|
+
- `typescript`: Type checking and compilation
|
|
480
|
+
- `vite`: Build system
|
|
481
|
+
- `vitest`: Unit testing
|
|
482
|
+
- `@swc/core`: Fast TypeScript compilation
|
|
483
|
+
- `eslint`, `prettier`: Code quality
|
|
484
|
+
|
|
485
|
+
## Build System
|
|
486
|
+
|
|
487
|
+
### Vite Configuration (`vite.config.ts`)
|
|
488
|
+
|
|
489
|
+
Fast builds with tree-shaking and optimization.
|
|
490
|
+
|
|
491
|
+
**Key Features**:
|
|
492
|
+
- SWC for TypeScript compilation (faster than tsc)
|
|
493
|
+
- Tree-shaking to reduce bundle size
|
|
494
|
+
- Git metadata injection (branch, commit hash)
|
|
495
|
+
- Executable permissions for binaries
|
|
496
|
+
- Source maps for debugging
|
|
497
|
+
|
|
498
|
+
**Configuration**:
|
|
499
|
+
```typescript
|
|
500
|
+
export default defineConfig({
|
|
501
|
+
build: {
|
|
502
|
+
lib: {
|
|
503
|
+
entry: {
|
|
504
|
+
'main': './src/main.ts',
|
|
505
|
+
'mcp-server': './src/mcp/server.ts'
|
|
506
|
+
},
|
|
507
|
+
formats: ['es']
|
|
508
|
+
},
|
|
509
|
+
target: 'node24',
|
|
510
|
+
rollupOptions: {
|
|
511
|
+
external: [/^node:/, 'commander', 'winston', ...]
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
plugins: [
|
|
515
|
+
swc.vite(),
|
|
516
|
+
gitMetadata()
|
|
517
|
+
]
|
|
518
|
+
});
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Build Output**:
|
|
522
|
+
- `dist/main.js`: CLI entry point
|
|
523
|
+
- `dist/mcp-server.js`: MCP server entry point
|
|
524
|
+
- Both with executable permissions
|
|
525
|
+
|
|
526
|
+
**Design Decisions**:
|
|
527
|
+
- Vite for speed (<30s builds)
|
|
528
|
+
- SWC over tsc (5x faster)
|
|
529
|
+
- External dependencies (not bundled)
|
|
530
|
+
- ESM format (modern Node.js)
|
|
531
|
+
|
|
532
|
+
## Testing Strategy
|
|
533
|
+
|
|
534
|
+
### Test Structure
|
|
535
|
+
|
|
536
|
+
```
|
|
537
|
+
tests/
|
|
538
|
+
├── utils/
|
|
539
|
+
│ └── config.test.ts # Configuration tests
|
|
540
|
+
├── mcp/
|
|
541
|
+
│ ├── tools.test.ts # MCP tool tests
|
|
542
|
+
│ ├── resources.test.ts # MCP resource tests
|
|
543
|
+
│ └── prompts/
|
|
544
|
+
│ └── index.test.ts # MCP prompt tests
|
|
545
|
+
├── application.test.ts # CLI application tests
|
|
546
|
+
├── constants.test.ts # Constants tests
|
|
547
|
+
├── logging.test.ts # Logging tests
|
|
548
|
+
└── commands/
|
|
549
|
+
├── commit.test.ts # Integration tests (excluded from CI)
|
|
550
|
+
└── release.test.ts # Integration tests (excluded from CI)
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Test Coverage
|
|
554
|
+
|
|
555
|
+
Target: **70%+** across all metrics
|
|
556
|
+
|
|
557
|
+
Current: **85%+** achieved
|
|
558
|
+
|
|
559
|
+
**Coverage Exclusions**:
|
|
560
|
+
- `src/main.ts`: Entry point (no logic)
|
|
561
|
+
- `src/types.ts`: Type definitions
|
|
562
|
+
- `src/application.ts`: CLI integration (requires Commander parse)
|
|
563
|
+
- `src/commands/release.ts`: Complex integration (requires git + AI)
|
|
564
|
+
- `src/mcp/server.ts`: MCP server integration (requires stdio)
|
|
565
|
+
|
|
566
|
+
**Vitest Configuration**:
|
|
567
|
+
```typescript
|
|
568
|
+
export default defineConfig({
|
|
569
|
+
test: {
|
|
570
|
+
globals: false,
|
|
571
|
+
environment: 'node',
|
|
572
|
+
include: ['tests/**/*.test.ts'],
|
|
573
|
+
exclude: ['tests/commands/**/*.test.ts'],
|
|
574
|
+
coverage: {
|
|
575
|
+
provider: 'v8',
|
|
576
|
+
thresholds: {
|
|
577
|
+
statements: 70,
|
|
578
|
+
branches: 70,
|
|
579
|
+
functions: 70,
|
|
580
|
+
lines: 70
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Design Decisions**:
|
|
588
|
+
- Vitest for speed and modern features
|
|
589
|
+
- V8 coverage for accuracy
|
|
590
|
+
- Exclude integration tests (require git repo)
|
|
591
|
+
- Mock external dependencies (@grunnverk packages)
|
|
592
|
+
|
|
593
|
+
### Mocking Strategy
|
|
594
|
+
|
|
595
|
+
Mock external dependencies for unit tests:
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
vi.mock('@grunnverk/commands-git', () => ({
|
|
599
|
+
commitCommand: vi.fn()
|
|
600
|
+
}));
|
|
601
|
+
|
|
602
|
+
vi.mock('@grunnverk/git-tools', () => ({
|
|
603
|
+
getGitStatus: vi.fn(),
|
|
604
|
+
getGitDiff: vi.fn()
|
|
605
|
+
}));
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
**Why**: Isolate units, fast tests, no side effects
|
|
609
|
+
|
|
610
|
+
## Type System
|
|
611
|
+
|
|
612
|
+
### Type Alignment
|
|
613
|
+
|
|
614
|
+
Kilde aligns with @grunnverk/core types:
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
import { Config, ReleaseConfig } from '@grunnverk/core';
|
|
618
|
+
|
|
619
|
+
// Use core types throughout
|
|
620
|
+
export async function releaseCommand(config: Config): Promise<void> {
|
|
621
|
+
const releaseConfig = config.release as ReleaseConfig;
|
|
622
|
+
// ...
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
**Design Decisions**:
|
|
627
|
+
- Import types from core (single source of truth)
|
|
628
|
+
- Use type assertions for non-standard fields
|
|
629
|
+
- TypeScript strict mode for safety
|
|
630
|
+
- Literal types for MCP protocol (`'text' as const`)
|
|
631
|
+
|
|
632
|
+
### MCP Type Safety
|
|
633
|
+
|
|
634
|
+
MCP requires literal types for protocol compliance:
|
|
635
|
+
|
|
636
|
+
```typescript
|
|
637
|
+
// Wrong
|
|
638
|
+
return { type: 'text', text: '...' };
|
|
639
|
+
|
|
640
|
+
// Right
|
|
641
|
+
return { type: 'text' as const, text: '...' };
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
**Why**: TypeScript unions require exact literals
|
|
645
|
+
|
|
646
|
+
## Error Handling
|
|
647
|
+
|
|
648
|
+
### Strategy
|
|
649
|
+
|
|
650
|
+
1. **Catch at boundaries**: CLI, MCP tools
|
|
651
|
+
2. **Log all errors**: With stack traces in debug mode
|
|
652
|
+
3. **User-friendly messages**: No stack traces in production
|
|
653
|
+
4. **Exit codes**: Standard codes for automation
|
|
654
|
+
|
|
655
|
+
**Example**:
|
|
656
|
+
```typescript
|
|
657
|
+
try {
|
|
658
|
+
await commitCommand(config);
|
|
659
|
+
} catch (error) {
|
|
660
|
+
logger.error('Commit failed', { error });
|
|
661
|
+
|
|
662
|
+
if (config.debug) {
|
|
663
|
+
console.error(error);
|
|
664
|
+
} else {
|
|
665
|
+
console.error(`Error: ${error.message}`);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
process.exit(1);
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
## Performance
|
|
673
|
+
|
|
674
|
+
### Build Performance
|
|
675
|
+
|
|
676
|
+
- **Target**: <30 seconds
|
|
677
|
+
- **Achieved**: ~30 seconds
|
|
678
|
+
- **Optimization**: SWC compilation, parallel builds
|
|
679
|
+
|
|
680
|
+
### Runtime Performance
|
|
681
|
+
|
|
682
|
+
- **Lazy loading**: Load dependencies only when needed
|
|
683
|
+
- **Streaming**: Stream large git outputs
|
|
684
|
+
- **Caching**: Cache config parsing (in-memory)
|
|
685
|
+
|
|
686
|
+
## Security
|
|
687
|
+
|
|
688
|
+
### API Key Management
|
|
689
|
+
|
|
690
|
+
- Store in environment variables
|
|
691
|
+
- Redact in logs
|
|
692
|
+
- Never commit to git
|
|
693
|
+
|
|
694
|
+
### Git Operations
|
|
695
|
+
|
|
696
|
+
- Validate repository before operations
|
|
697
|
+
- Check for clean state
|
|
698
|
+
- Use `--dry-run` for testing
|
|
699
|
+
|
|
700
|
+
### AI Service
|
|
701
|
+
|
|
702
|
+
- Sanitize prompts (remove secrets)
|
|
703
|
+
- Rate limit API calls
|
|
704
|
+
- Handle API errors gracefully
|
|
705
|
+
|
|
706
|
+
## Design Principles
|
|
707
|
+
|
|
708
|
+
### 1. Simplicity
|
|
709
|
+
Two commands, clear purpose, minimal options.
|
|
710
|
+
|
|
711
|
+
### 2. Reusability
|
|
712
|
+
Leverage @grunnverk ecosystem, avoid duplication.
|
|
713
|
+
|
|
714
|
+
### 3. Flexibility
|
|
715
|
+
Configuration-driven behavior, CLI overrides.
|
|
716
|
+
|
|
717
|
+
### 4. Safety
|
|
718
|
+
Interactive mode by default, dry-run for testing.
|
|
719
|
+
|
|
720
|
+
### 5. Transparency
|
|
721
|
+
Clear logging, reviewable operations.
|
|
722
|
+
|
|
723
|
+
### 6. Language-Agnostic
|
|
724
|
+
Pure git operations, works with any language.
|
|
725
|
+
|
|
726
|
+
### 7. Host-Agnostic
|
|
727
|
+
No GitHub API dependencies, works with any git host.
|
|
728
|
+
|
|
729
|
+
## Future Architecture
|
|
730
|
+
|
|
731
|
+
### Extensibility
|
|
732
|
+
|
|
733
|
+
Potential plugin system:
|
|
734
|
+
|
|
735
|
+
```typescript
|
|
736
|
+
interface KildePlugin {
|
|
737
|
+
name: string;
|
|
738
|
+
commands?: Command[];
|
|
739
|
+
mcpTools?: Tool[];
|
|
740
|
+
mcpResources?: Resource[];
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// Load plugins
|
|
744
|
+
const plugins = await loadPlugins();
|
|
745
|
+
for (const plugin of plugins) {
|
|
746
|
+
registerPlugin(plugin);
|
|
747
|
+
}
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### Additional AI Providers
|
|
751
|
+
|
|
752
|
+
Support for more AI models:
|
|
753
|
+
|
|
754
|
+
```typescript
|
|
755
|
+
interface AIProvider {
|
|
756
|
+
name: string;
|
|
757
|
+
generateCommitMessage(diff: string): Promise<string>;
|
|
758
|
+
generateReleaseNotes(commits: Commit[]): Promise<string>;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Register providers
|
|
762
|
+
registerProvider(new OpenAIProvider());
|
|
763
|
+
registerProvider(new AnthropicProvider());
|
|
764
|
+
registerProvider(new LocalModelProvider());
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
## Next Steps
|
|
768
|
+
|
|
769
|
+
- [Overview Guide](./overview.md) - High-level overview
|
|
770
|
+
- [Commands Guide](./commands.md) - Command reference
|
|
771
|
+
- [Configuration Guide](./configuration.md) - Configuration options
|
|
772
|
+
- [MCP Integration Guide](./mcp-integration.md) - MCP setup
|
|
773
|
+
|
|
774
|
+
## Contributing
|
|
775
|
+
|
|
776
|
+
See [CONTRIBUTING.md](../CONTRIBUTING.md) for development setup and guidelines.
|