Skip to content

Commit 23d9da7

Browse files
committed
SpecMem Kiro Integration
1 parent d59462a commit 23d9da7

140 files changed

Lines changed: 29399 additions & 414 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
# Design Document
2+
3+
## Overview
4+
5+
The Kiro Config Indexer extends SpecMem's existing Kiro adapter to comprehensively index all Kiro CLI configuration artifacts. This includes project-level steering files, MCP server configurations, hooks, and agent settings. The feature enables SpecMem to provide context-aware responses about project configuration and automatically include relevant guidelines when generating context bundles.
6+
7+
## Architecture
8+
9+
```
10+
┌─────────────────────────────────────────────────────────────────┐
11+
│ .kiro/ Directory │
12+
├─────────────────────────────────────────────────────────────────┤
13+
│ steering/ settings/ hooks/ │
14+
│ ├── python.md ├── mcp.json ├── validate.json │
15+
│ ├── testing.md └── agent.json └── coverage.json │
16+
│ └── security.md │
17+
└─────────────────────────────────────────────────────────────────┘
18+
19+
20+
┌─────────────────────────────────────────────────────────────────┐
21+
│ KiroConfigIndexer │
22+
├─────────────────────────────────────────────────────────────────┤
23+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
24+
│ │ Steering │ │ MCP │ │ Hooks │ │
25+
│ │ Parser │ │ Parser │ │ Parser │ │
26+
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
27+
│ │ │ │ │
28+
│ └────────────────┼────────────────┘ │
29+
│ ▼ │
30+
│ ┌───────────────────────┐ │
31+
│ │ SpecBlock Factory │ │
32+
│ └───────────┬───────────┘ │
33+
└──────────────────────────┼──────────────────────────────────────┘
34+
35+
36+
┌─────────────────────────────────────────────────────────────────┐
37+
│ Memory Bank │
38+
│ ┌─────────────────────────────────────────────────────────┐ │
39+
│ │ SpecBlocks with tags: steering, mcp, hook, config │ │
40+
│ └─────────────────────────────────────────────────────────┘ │
41+
└─────────────────────────────────────────────────────────────────┘
42+
```
43+
44+
## Components and Interfaces
45+
46+
### KiroConfigIndexer
47+
48+
Main class that orchestrates indexing of all Kiro configuration artifacts.
49+
50+
```python
51+
@dataclass
52+
class KiroConfigIndexer:
53+
"""Indexes Kiro CLI configuration artifacts."""
54+
55+
workspace_path: Path
56+
57+
def index_all(self) -> list[SpecBlock]:
58+
"""Index all Kiro configuration files."""
59+
...
60+
61+
def index_steering(self) -> list[SpecBlock]:
62+
"""Index steering files from .kiro/steering/."""
63+
...
64+
65+
def index_mcp_config(self) -> list[SpecBlock]:
66+
"""Index MCP configuration from .kiro/settings/mcp.json."""
67+
...
68+
69+
def index_hooks(self) -> list[SpecBlock]:
70+
"""Index hooks from .kiro/hooks/."""
71+
...
72+
73+
def get_steering_for_file(self, file_path: str) -> list[SpecBlock]:
74+
"""Get steering files applicable to a specific file."""
75+
...
76+
77+
def get_available_tools(self) -> list[MCPToolInfo]:
78+
"""Get list of available (enabled) MCP tools."""
79+
...
80+
81+
def get_hooks_for_trigger(
82+
self,
83+
trigger: str,
84+
file_path: str | None = None
85+
) -> list[HookInfo]:
86+
"""Get hooks matching a trigger type and optional file pattern."""
87+
...
88+
```
89+
90+
### SteeringParser
91+
92+
Parses steering files with YAML frontmatter support.
93+
94+
```python
95+
@dataclass
96+
class SteeringFile:
97+
"""Parsed steering file."""
98+
99+
path: Path
100+
content: str
101+
inclusion: Literal["always", "fileMatch", "manual"]
102+
file_match_pattern: str | None
103+
title: str
104+
105+
def matches_file(self, file_path: str) -> bool:
106+
"""Check if this steering applies to a file."""
107+
...
108+
109+
110+
class SteeringParser:
111+
"""Parses steering files with frontmatter."""
112+
113+
def parse(self, file_path: Path) -> SteeringFile:
114+
"""Parse a steering file."""
115+
...
116+
117+
def parse_frontmatter(self, content: str) -> dict[str, Any]:
118+
"""Extract YAML frontmatter from content."""
119+
...
120+
```
121+
122+
### MCPConfigParser
123+
124+
Parses MCP server configuration.
125+
126+
```python
127+
@dataclass
128+
class MCPServerInfo:
129+
"""Parsed MCP server configuration."""
130+
131+
name: str
132+
command: str
133+
args: list[str]
134+
env: dict[str, str]
135+
disabled: bool
136+
auto_approve: list[str]
137+
138+
139+
@dataclass
140+
class MCPToolInfo:
141+
"""Information about an MCP tool."""
142+
143+
server_name: str
144+
tool_name: str
145+
description: str
146+
auto_approved: bool
147+
148+
149+
class MCPConfigParser:
150+
"""Parses MCP configuration."""
151+
152+
def parse(self, config_path: Path) -> list[MCPServerInfo]:
153+
"""Parse mcp.json configuration."""
154+
...
155+
156+
def get_tools(self, servers: list[MCPServerInfo]) -> list[MCPToolInfo]:
157+
"""Extract tool information from servers."""
158+
...
159+
```
160+
161+
### HookParser
162+
163+
Parses hook configuration files.
164+
165+
```python
166+
@dataclass
167+
class HookInfo:
168+
"""Parsed hook configuration."""
169+
170+
name: str
171+
description: str
172+
trigger: Literal["file_save", "manual", "session_start"]
173+
file_pattern: str | None
174+
action: str
175+
enabled: bool
176+
177+
def matches_file(self, file_path: str) -> bool:
178+
"""Check if hook's file pattern matches a file."""
179+
...
180+
181+
182+
class HookParser:
183+
"""Parses hook configuration files."""
184+
185+
def parse(self, hook_path: Path) -> HookInfo:
186+
"""Parse a hook JSON file."""
187+
...
188+
```
189+
190+
## Data Models
191+
192+
### SteeringFile
193+
194+
```python
195+
@dataclass
196+
class SteeringFile:
197+
path: Path
198+
content: str
199+
inclusion: Literal["always", "fileMatch", "manual"]
200+
file_match_pattern: str | None
201+
title: str
202+
```
203+
204+
### MCPServerInfo
205+
206+
```python
207+
@dataclass
208+
class MCPServerInfo:
209+
name: str
210+
command: str
211+
args: list[str]
212+
env: dict[str, str]
213+
disabled: bool
214+
auto_approve: list[str]
215+
```
216+
217+
### HookInfo
218+
219+
```python
220+
@dataclass
221+
class HookInfo:
222+
name: str
223+
description: str
224+
trigger: Literal["file_save", "manual", "session_start"]
225+
file_pattern: str | None
226+
action: str
227+
enabled: bool
228+
```
229+
230+
### KiroConfigSummary
231+
232+
```python
233+
@dataclass
234+
class KiroConfigSummary:
235+
steering_files: list[SteeringFile]
236+
mcp_servers: list[MCPServerInfo]
237+
hooks: list[HookInfo]
238+
total_tools: int
239+
enabled_servers: int
240+
active_hooks: int
241+
```
242+
243+
## Correctness Properties
244+
245+
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
246+
247+
### Property 1: Steering File Parsing Completeness
248+
249+
*For any* directory containing valid steering markdown files, parsing SHALL produce one SpecBlock per file, and each SpecBlock SHALL contain the file's content.
250+
251+
**Validates: Requirements 1.1**
252+
253+
### Property 2: Frontmatter Round-Trip
254+
255+
*For any* valid YAML frontmatter with `inclusion` and `fileMatchPattern` fields, parsing and re-serializing SHALL preserve the original values.
256+
257+
**Validates: Requirements 1.2**
258+
259+
### Property 3: File Pattern Matching Consistency
260+
261+
*For any* steering file with a `fileMatchPattern` and any file path, the `matches_file()` method SHALL return true if and only if the file path matches the glob pattern according to standard glob semantics.
262+
263+
**Validates: Requirements 1.3, 5.1, 5.2**
264+
265+
### Property 4: Inclusion Mode Priority Mapping
266+
267+
*For any* steering file, the resulting SpecBlock's priority SHALL be determined by its inclusion mode: "always" → high priority (pinned), "fileMatch" → normal priority, "manual" → low priority (not auto-included).
268+
269+
**Validates: Requirements 1.4, 1.5**
270+
271+
### Property 5: MCP Server Parsing Completeness
272+
273+
*For any* valid mcp.json configuration, parsing SHALL produce one SpecBlock per defined server, and each SpecBlock SHALL contain the server name and command.
274+
275+
**Validates: Requirements 2.1**
276+
277+
### Property 6: MCP Tool Extraction
278+
279+
*For any* MCP server with tool definitions, the parser SHALL extract all tools, and each tool's SpecBlock SHALL contain its name and description.
280+
281+
**Validates: Requirements 2.2**
282+
283+
### Property 7: Disabled Server Filtering
284+
285+
*For any* query for available tools, the result SHALL exclude tools from servers where `disabled: true`, and SHALL include tools from all enabled servers.
286+
287+
**Validates: Requirements 2.3, 2.4**
288+
289+
### Property 8: Hook Parsing Completeness
290+
291+
*For any* directory containing valid hook JSON files, parsing SHALL produce one SpecBlock per hook file.
292+
293+
**Validates: Requirements 3.1**
294+
295+
### Property 9: Hook Trigger Filtering
296+
297+
*For any* query for hooks by trigger type and file path, the result SHALL include only hooks where the trigger matches AND (file_pattern is null OR file_pattern matches the path).
298+
299+
**Validates: Requirements 3.2, 3.3**
300+
301+
### Property 10: Always-Included Steering
302+
303+
*For any* steering file with `inclusion: always`, querying steering for any file path SHALL include that steering file in the results.
304+
305+
**Validates: Requirements 5.3**
306+
307+
### Property 11: Context Bundle Steering Inclusion
308+
309+
*For any* context bundle generated for changed files, the bundle SHALL include content from all steering files where `inclusion: always` OR `fileMatchPattern` matches any changed file.
310+
311+
**Validates: Requirements 6.1, 6.2**
312+
313+
### Property 12: Context Bundle Hook Mention
314+
315+
*For any* context bundle generated for changed files, if a hook with `trigger: file_save` has a `filePattern` matching any changed file, the bundle SHALL mention this hook.
316+
317+
**Validates: Requirements 6.4**
318+
319+
## Error Handling
320+
321+
| Condition | Handling |
322+
|-----------|----------|
323+
| Missing `.kiro/steering/` directory | Return empty list, no error |
324+
| Missing `.kiro/settings/mcp.json` | Return empty list, no error |
325+
| Missing `.kiro/hooks/` directory | Return empty list, no error |
326+
| Malformed YAML frontmatter | Log warning, parse content without frontmatter |
327+
| Invalid JSON in mcp.json | Log error, return empty list |
328+
| Invalid JSON in hook file | Log warning, skip that hook |
329+
| Invalid glob pattern | Log warning, treat as non-matching |
330+
331+
## Testing Strategy
332+
333+
### Property-Based Testing
334+
335+
The implementation will use **Hypothesis** for property-based testing with a minimum of 100 iterations per property.
336+
337+
Each property test will be annotated with:
338+
```python
339+
# **Feature: kiro-config-indexer, Property N: Property Name**
340+
# **Validates: Requirements X.Y**
341+
```
342+
343+
### Test Strategies
344+
345+
1. **Steering files**: Generate random markdown content with valid/invalid frontmatter
346+
2. **MCP config**: Generate random JSON with varying numbers of servers and tools
347+
3. **Hooks**: Generate random hook configurations with different triggers and patterns
348+
4. **File matching**: Generate random glob patterns and file paths to test matching
349+
350+
### Unit Tests
351+
352+
- Parse steering file with no frontmatter
353+
- Parse steering file with partial frontmatter
354+
- Parse MCP config with disabled servers
355+
- Parse hook with missing optional fields
356+
- CLI command output formatting

0 commit comments

Comments
 (0)