@eddacraft/anvil-adapters 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/AGENTS.md +180 -0
- package/BMAD_ADAPTER_SPEC.md +489 -0
- package/LICENSE +14 -0
- package/README.md +500 -0
- package/dist/aps-markdown/adapter.d.ts +102 -0
- package/dist/aps-markdown/adapter.d.ts.map +1 -0
- package/dist/aps-markdown/adapter.js +351 -0
- package/dist/aps-markdown/index.d.ts +8 -0
- package/dist/aps-markdown/index.d.ts.map +1 -0
- package/dist/aps-markdown/index.js +7 -0
- package/dist/base/file-discovery.d.ts +63 -0
- package/dist/base/file-discovery.d.ts.map +1 -0
- package/dist/base/file-discovery.js +246 -0
- package/dist/base/index.d.ts +10 -0
- package/dist/base/index.d.ts.map +1 -0
- package/dist/base/index.js +9 -0
- package/dist/base/registry.d.ts +155 -0
- package/dist/base/registry.d.ts.map +1 -0
- package/dist/base/registry.js +227 -0
- package/dist/base/testing.d.ts +102 -0
- package/dist/base/testing.d.ts.map +1 -0
- package/dist/base/testing.js +221 -0
- package/dist/base/types.d.ts +255 -0
- package/dist/base/types.d.ts.map +1 -0
- package/dist/base/types.js +78 -0
- package/dist/base/utils.d.ts +127 -0
- package/dist/base/utils.d.ts.map +1 -0
- package/dist/base/utils.js +254 -0
- package/dist/bmad/format-adapter.d.ts +76 -0
- package/dist/bmad/format-adapter.d.ts.map +1 -0
- package/dist/bmad/format-adapter.js +186 -0
- package/dist/bmad/index.d.ts +12 -0
- package/dist/bmad/index.d.ts.map +1 -0
- package/dist/bmad/index.js +10 -0
- package/dist/bmad/parser.d.ts +12 -0
- package/dist/bmad/parser.d.ts.map +1 -0
- package/dist/bmad/parser.js +181 -0
- package/dist/bmad/serializer.d.ts +16 -0
- package/dist/bmad/serializer.d.ts.map +1 -0
- package/dist/bmad/serializer.js +170 -0
- package/dist/bmad/types.d.ts +127 -0
- package/dist/bmad/types.d.ts.map +1 -0
- package/dist/bmad/types.js +47 -0
- package/dist/bmad/utils.d.ts +120 -0
- package/dist/bmad/utils.d.ts.map +1 -0
- package/dist/bmad/utils.js +480 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +2 -0
- package/dist/common/registry.d.ts +18 -0
- package/dist/common/registry.d.ts.map +1 -0
- package/dist/common/registry.js +58 -0
- package/dist/common/types.d.ts +68 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +12 -0
- package/dist/generic/format-adapter.d.ts +64 -0
- package/dist/generic/format-adapter.d.ts.map +1 -0
- package/dist/generic/format-adapter.js +159 -0
- package/dist/generic/index.d.ts +10 -0
- package/dist/generic/index.d.ts.map +1 -0
- package/dist/generic/index.js +9 -0
- package/dist/generic/parser.d.ts +11 -0
- package/dist/generic/parser.d.ts.map +1 -0
- package/dist/generic/parser.js +106 -0
- package/dist/generic/serializer.d.ts +11 -0
- package/dist/generic/serializer.d.ts.map +1 -0
- package/dist/generic/serializer.js +118 -0
- package/dist/generic/types.d.ts +52 -0
- package/dist/generic/types.d.ts.map +1 -0
- package/dist/generic/types.js +6 -0
- package/dist/generic/utils.d.ts +51 -0
- package/dist/generic/utils.d.ts.map +1 -0
- package/dist/generic/utils.js +232 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/speckit/export.d.ts +22 -0
- package/dist/speckit/export.d.ts.map +1 -0
- package/dist/speckit/export.js +384 -0
- package/dist/speckit/format-adapter.d.ts +104 -0
- package/dist/speckit/format-adapter.d.ts.map +1 -0
- package/dist/speckit/format-adapter.js +488 -0
- package/dist/speckit/import-v2.d.ts +33 -0
- package/dist/speckit/import-v2.d.ts.map +1 -0
- package/dist/speckit/import-v2.js +361 -0
- package/dist/speckit/import.d.ts +16 -0
- package/dist/speckit/import.d.ts.map +1 -0
- package/dist/speckit/import.js +247 -0
- package/dist/speckit/index.d.ts +5 -0
- package/dist/speckit/index.d.ts.map +1 -0
- package/dist/speckit/index.js +4 -0
- package/dist/speckit/parser.d.ts +28 -0
- package/dist/speckit/parser.d.ts.map +1 -0
- package/dist/speckit/parser.js +283 -0
- package/dist/speckit/parsers/plan-parser.d.ts +71 -0
- package/dist/speckit/parsers/plan-parser.d.ts.map +1 -0
- package/dist/speckit/parsers/plan-parser.js +216 -0
- package/dist/speckit/parsers/spec-parser.d.ts +67 -0
- package/dist/speckit/parsers/spec-parser.d.ts.map +1 -0
- package/dist/speckit/parsers/spec-parser.js +255 -0
- package/dist/speckit/parsers/tasks-parser.d.ts +57 -0
- package/dist/speckit/parsers/tasks-parser.d.ts.map +1 -0
- package/dist/speckit/parsers/tasks-parser.js +157 -0
- package/package.json +23 -0
- package/project.json +29 -0
- package/src/__tests__/adapter-edge-cases.test.ts +937 -0
- package/src/__tests__/bmad-format-adapter.test.ts +1470 -0
- package/src/__tests__/fixtures/aps/expected-output.json +83 -0
- package/src/__tests__/fixtures/bmad/invalid-malformed-yaml.md +16 -0
- package/src/__tests__/fixtures/bmad/invalid-no-requirements.md +23 -0
- package/src/__tests__/fixtures/bmad/invalid-only-yaml.md +16 -0
- package/src/__tests__/fixtures/bmad/invalid-too-short.md +3 -0
- package/src/__tests__/fixtures/bmad/invalid-wrong-format.md +40 -0
- package/src/__tests__/fixtures/bmad/valid-agent.md +27 -0
- package/src/__tests__/fixtures/bmad/valid-architecture.md +116 -0
- package/src/__tests__/fixtures/bmad/valid-complex-prd.md +161 -0
- package/src/__tests__/fixtures/bmad/valid-epic.md +73 -0
- package/src/__tests__/fixtures/bmad/valid-minimal-prd.md +19 -0
- package/src/__tests__/fixtures/bmad/valid-prd.md +107 -0
- package/src/__tests__/fixtures/bmad/valid-story.md +107 -0
- package/src/__tests__/fixtures/bmad/valid-task.md +79 -0
- package/src/__tests__/fixtures/bmad/valid-v6-prd.md +35 -0
- package/src/__tests__/fixtures/generic/plan-detailed.md +39 -0
- package/src/__tests__/fixtures/generic/prd-simple.md +27 -0
- package/src/__tests__/fixtures/generic/rfc-example.md +26 -0
- package/src/__tests__/fixtures/generic/todo-list.md +23 -0
- package/src/__tests__/fixtures/speckit/sample-plan.md +63 -0
- package/src/__tests__/fixtures/speckit/sample-spec-namespaced.md +50 -0
- package/src/__tests__/fixtures/speckit/sample-spec.md +105 -0
- package/src/__tests__/fixtures/speckit/sample-tasks.md +87 -0
- package/src/__tests__/fixtures/speckit-official/auth-feature/plan.md +272 -0
- package/src/__tests__/fixtures/speckit-official/auth-feature/spec.md +149 -0
- package/src/__tests__/fixtures/speckit-official/auth-feature/tasks.md +169 -0
- package/src/__tests__/generic-format-adapter.test.ts +398 -0
- package/src/__tests__/speckit-export.test.ts +233 -0
- package/src/__tests__/speckit-format-adapter.test.ts +832 -0
- package/src/__tests__/speckit-import-v2.test.ts +253 -0
- package/src/__tests__/speckit-import.test.ts +209 -0
- package/src/__tests__/speckit-parser.test.ts +219 -0
- package/src/__tests__/speckit-spec-parser.test.ts +120 -0
- package/src/aps-markdown/__tests__/__fixtures__/simple-leaf.aps.md +17 -0
- package/src/aps-markdown/__tests__/adapter.test.ts +393 -0
- package/src/aps-markdown/adapter.ts +455 -0
- package/src/aps-markdown/index.ts +8 -0
- package/src/base/__tests__/registry.test.ts +515 -0
- package/src/base/file-discovery.ts +305 -0
- package/src/base/index.ts +10 -0
- package/src/base/registry.ts +263 -0
- package/src/base/testing.ts +334 -0
- package/src/base/types.ts +342 -0
- package/src/base/utils.ts +306 -0
- package/src/bmad/format-adapter.ts +227 -0
- package/src/bmad/index.ts +21 -0
- package/src/bmad/parser.ts +224 -0
- package/src/bmad/serializer.ts +206 -0
- package/src/bmad/types.ts +135 -0
- package/src/bmad/utils.ts +575 -0
- package/src/common/index.ts +2 -0
- package/src/common/registry.ts +72 -0
- package/src/common/types.ts +84 -0
- package/src/generic/__tests__/serializer.test.ts +167 -0
- package/src/generic/format-adapter.ts +200 -0
- package/src/generic/index.ts +11 -0
- package/src/generic/parser.ts +129 -0
- package/src/generic/serializer.ts +134 -0
- package/src/generic/types.ts +53 -0
- package/src/generic/utils.ts +270 -0
- package/src/index.ts +48 -0
- package/src/speckit/export.ts +489 -0
- package/src/speckit/format-adapter.ts +595 -0
- package/src/speckit/import-v2.ts +445 -0
- package/src/speckit/import.ts +305 -0
- package/src/speckit/index.ts +4 -0
- package/src/speckit/parser.ts +351 -0
- package/src/speckit/parsers/plan-parser.ts +342 -0
- package/src/speckit/parsers/spec-parser.ts +379 -0
- package/src/speckit/parsers/tasks-parser.ts +246 -0
- package/tsconfig.json +26 -0
- package/tsconfig.lib.json +21 -0
- package/tsconfig.lib.tsbuildinfo +1 -0
- package/tsconfig.spec.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +14 -0
package/README.md
ADDED
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
# Anvil Format Adapters
|
|
2
|
+
|
|
3
|
+
Format adapters for converting between external planning formats (SpecKit, BMAD,
|
|
4
|
+
etc.) and Anvil Plan Specification (APS).
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The adapter framework provides a pluggable architecture for working with
|
|
9
|
+
different planning document formats. Users can continue using their preferred
|
|
10
|
+
format while benefiting from APS validation and gate execution internally.
|
|
11
|
+
|
|
12
|
+
## Architecture
|
|
13
|
+
|
|
14
|
+
### Core Concepts
|
|
15
|
+
|
|
16
|
+
- **FormatAdapter**: Interface for converting between external formats and APS
|
|
17
|
+
- **AdapterRegistry**: Central registry for adapter discovery and lookup
|
|
18
|
+
- **Auto-detection**: Content-based format detection with confidence scoring
|
|
19
|
+
- **Round-trip fidelity**: Parse and serialize maintain document integrity
|
|
20
|
+
|
|
21
|
+
### Package Structure
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
packages/adapters/
|
|
25
|
+
├── src/
|
|
26
|
+
│ ├── base/ # Framework core
|
|
27
|
+
│ │ ├── types.ts # Core interfaces and types
|
|
28
|
+
│ │ ├── registry.ts # Adapter registry
|
|
29
|
+
│ │ ├── utils.ts # Helper utilities
|
|
30
|
+
│ │ └── testing.ts # Testing utilities
|
|
31
|
+
│ ├── speckit/ # SpecKit adapter ✅
|
|
32
|
+
│ ├── bmad/ # BMAD adapter ✅
|
|
33
|
+
│ └── generic/ # Generic markdown adapter ✅
|
|
34
|
+
└── README.md
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### Using Adapters
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { registry } from '@eddacraft/anvil-adapters';
|
|
43
|
+
import { SpecKitAdapter } from '@eddacraft/anvil-adapters/speckit';
|
|
44
|
+
|
|
45
|
+
// Register adapter
|
|
46
|
+
const speckit = new SpecKitAdapter();
|
|
47
|
+
registry.register(speckit);
|
|
48
|
+
|
|
49
|
+
// Auto-detect format
|
|
50
|
+
const content = await fs.readFile('plan.md', 'utf-8');
|
|
51
|
+
const match = registry.detectAdapter(content);
|
|
52
|
+
|
|
53
|
+
if (match) {
|
|
54
|
+
console.log(`Detected: ${match.adapter.metadata.displayName}`);
|
|
55
|
+
console.log(`Confidence: ${match.detection.confidence}%`);
|
|
56
|
+
|
|
57
|
+
// Parse to APS
|
|
58
|
+
const result = await match.adapter.parse(content);
|
|
59
|
+
if (result.success) {
|
|
60
|
+
console.log('Parsed plan:', result.data);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Find adapter by format
|
|
65
|
+
const adapter = registry.getAdapterForFormat('speckit');
|
|
66
|
+
if (adapter) {
|
|
67
|
+
const result = await adapter.parse(content);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Creating Custom Adapters
|
|
72
|
+
|
|
73
|
+
See [ADAPTER_WORKFLOW_GUIDE.md](./ADAPTER_WORKFLOW_GUIDE.md) for:
|
|
74
|
+
|
|
75
|
+
- Complete workflow guide with real-world examples
|
|
76
|
+
- Technical deep dive into adapter implementation
|
|
77
|
+
- Step-by-step guide for adding new adapters
|
|
78
|
+
- CLI integration patterns
|
|
79
|
+
- Testing strategies
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
See [packages/adapters/src/base/](./src/base/) for complete API documentation.
|
|
84
|
+
|
|
85
|
+
### Key Interfaces
|
|
86
|
+
|
|
87
|
+
- `FormatAdapter` - Main adapter interface
|
|
88
|
+
- `AdapterRegistry` - Adapter registration and lookup
|
|
89
|
+
- `ParseResult` - Result of parsing external format to APS
|
|
90
|
+
- `SerializeResult` - Result of serializing APS to external format
|
|
91
|
+
- `DetectionResult` - Result of format detection
|
|
92
|
+
|
|
93
|
+
## Supported Formats
|
|
94
|
+
|
|
95
|
+
### SpecKit ✅ COMPLETE
|
|
96
|
+
|
|
97
|
+
GitHub's official spec-driven development format. Supports the complete spec-kit
|
|
98
|
+
workflow with three document types.
|
|
99
|
+
|
|
100
|
+
- **Extensions**: `spec.md`, `plan.md`, `tasks.md`
|
|
101
|
+
- **Status**: ✅ Fully implemented (November 2025)
|
|
102
|
+
- **Version**: 2.0.0
|
|
103
|
+
- **Code**: ~2,469 lines
|
|
104
|
+
- **Tests**: 114 tests (45 format adapter + 69 parsers, all passing ✅)
|
|
105
|
+
- **Coverage**: >95%
|
|
106
|
+
|
|
107
|
+
#### Document Types
|
|
108
|
+
|
|
109
|
+
**spec.md** - Requirements and user scenarios (WHAT and WHY)
|
|
110
|
+
|
|
111
|
+
- Feature metadata (branch, date, status)
|
|
112
|
+
- User scenarios & testing (prioritized user stories with acceptance criteria)
|
|
113
|
+
- Functional requirements (testable requirements with clarification markers)
|
|
114
|
+
- Key entities (data model definitions)
|
|
115
|
+
- Success criteria (quantitative and qualitative metrics)
|
|
116
|
+
|
|
117
|
+
**plan.md** - Technical implementation (HOW)
|
|
118
|
+
|
|
119
|
+
- Summary of technical approach
|
|
120
|
+
- Technical context (language, dependencies, constraints)
|
|
121
|
+
- Constitution check (compliance with project principles)
|
|
122
|
+
- Project structure (directory layout, file organisation)
|
|
123
|
+
- Implementation details (API endpoints, database schema, etc.)
|
|
124
|
+
- Complexity tracking (design decisions and justifications)
|
|
125
|
+
|
|
126
|
+
**tasks.md** - Executable breakdown
|
|
127
|
+
|
|
128
|
+
- Tasks organised by phases with IDs
|
|
129
|
+
- Parallel execution markers
|
|
130
|
+
- Checkpoints after each phase
|
|
131
|
+
- Dependencies and execution order
|
|
132
|
+
- Implementation strategies
|
|
133
|
+
|
|
134
|
+
#### Usage Example
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { SpecKitImportAdapterV2 } from '@eddacraft/anvil-adapters/speckit';
|
|
138
|
+
|
|
139
|
+
const adapter = new SpecKitImportAdapterV2();
|
|
140
|
+
|
|
141
|
+
// Import complete spec-kit feature directory
|
|
142
|
+
const result = await adapter.convertToAPS({
|
|
143
|
+
format: 'speckit',
|
|
144
|
+
version: '2.0.0',
|
|
145
|
+
content: {
|
|
146
|
+
spec: { content: specMdContent },
|
|
147
|
+
plan: { content: planMdContent },
|
|
148
|
+
tasks: { content: tasksMdContent },
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (result.success) {
|
|
153
|
+
// APS plan with full metadata from all documents
|
|
154
|
+
const plan = result.data;
|
|
155
|
+
|
|
156
|
+
// Access spec.md data
|
|
157
|
+
console.log(plan.metadata?.userScenarios);
|
|
158
|
+
console.log(plan.metadata?.clarifications);
|
|
159
|
+
|
|
160
|
+
// Access plan.md data
|
|
161
|
+
console.log(plan.metadata?.technicalContext);
|
|
162
|
+
console.log(plan.metadata?.implementationDetails);
|
|
163
|
+
|
|
164
|
+
// Access tasks.md data
|
|
165
|
+
console.log(plan.metadata?.phases);
|
|
166
|
+
console.log(plan.metadata?.taskDependencies);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### APS Mapping
|
|
171
|
+
|
|
172
|
+
- **User Scenarios** → `proposed_changes` with scenario metadata (user story,
|
|
173
|
+
acceptance criteria, edge cases)
|
|
174
|
+
- **Functional Requirements** → `metadata.requirements.functional[]`
|
|
175
|
+
- **Key Entities** → `metadata.requirements.entities[]`
|
|
176
|
+
- **Success Criteria** → `metadata.successCriteria`
|
|
177
|
+
- **Clarifications** → `metadata.clarifications[]` (all `[NEEDS CLARIFICATION]`
|
|
178
|
+
markers)
|
|
179
|
+
- **Technical Context** → `metadata.technicalContext`
|
|
180
|
+
- **Project Structure** → `metadata.projectStructure`
|
|
181
|
+
- **Implementation Details** → `metadata.implementationDetails`
|
|
182
|
+
- **Phases & Tasks** → `metadata.phases[]`, `metadata.taskDependencies[]`
|
|
183
|
+
|
|
184
|
+
### BMAD ✅ COMPLETE
|
|
185
|
+
|
|
186
|
+
Business Model and Architecture Document format - enterprise requirements and
|
|
187
|
+
PRD format.
|
|
188
|
+
|
|
189
|
+
- **Extensions**: `.md` (PRD, Architecture, Epic, Story formats)
|
|
190
|
+
- **Status**: ✅ Fully implemented (November 2025)
|
|
191
|
+
- **Version**: 1.0.0
|
|
192
|
+
- **Code**: ~800 lines
|
|
193
|
+
- **Tests**: 86 tests (all passing ✅) - exceeds 50+ target
|
|
194
|
+
- **Coverage**: >95%
|
|
195
|
+
- **CLI Integration**: 100% (validate, gate, export commands)
|
|
196
|
+
|
|
197
|
+
#### Document Types Supported
|
|
198
|
+
|
|
199
|
+
**PRD (Product Requirements Document)**
|
|
200
|
+
|
|
201
|
+
- Functional Requirements (FR-01, FR-02, etc.)
|
|
202
|
+
- Non-Functional Requirements (NFR-01, NFR-02, etc.)
|
|
203
|
+
- Epics and User Stories (US-01, US-02, etc.)
|
|
204
|
+
- YAML front-matter metadata
|
|
205
|
+
- Change log tables
|
|
206
|
+
|
|
207
|
+
**Architecture Documents**
|
|
208
|
+
|
|
209
|
+
- Technical Summary
|
|
210
|
+
- High Level Architecture
|
|
211
|
+
- System Components
|
|
212
|
+
- Tech Stack
|
|
213
|
+
- API Specifications
|
|
214
|
+
|
|
215
|
+
**Epic and Story Documents**
|
|
216
|
+
|
|
217
|
+
- Epic goals and related stories
|
|
218
|
+
- User story format: "As a... I want... so that..."
|
|
219
|
+
- Acceptance criteria
|
|
220
|
+
- Implementation details
|
|
221
|
+
|
|
222
|
+
#### Format Detection
|
|
223
|
+
|
|
224
|
+
Confidence-based algorithm with 5 weighted indicators (100-point scale):
|
|
225
|
+
|
|
226
|
+
- YAML front-matter: 30 points
|
|
227
|
+
- Requirement identifiers (FR/NFR/US): 25 points
|
|
228
|
+
- User story format: 20 points
|
|
229
|
+
- Change log table: 15 points
|
|
230
|
+
- Document title: 10 points
|
|
231
|
+
- **Detection threshold**: 50%
|
|
232
|
+
- **Typical confidence**: 90-100% for valid BMAD documents
|
|
233
|
+
|
|
234
|
+
#### Usage Example
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { BMADFormatAdapter } from '@eddacraft/anvil-adapters/bmad';
|
|
238
|
+
|
|
239
|
+
const adapter = new BMADFormatAdapter();
|
|
240
|
+
|
|
241
|
+
// Detect BMAD format
|
|
242
|
+
const detection = adapter.detect(content);
|
|
243
|
+
console.log(`Confidence: ${detection.confidence}%`);
|
|
244
|
+
|
|
245
|
+
// Parse BMAD to APS
|
|
246
|
+
const parseResult = await adapter.parse(content);
|
|
247
|
+
if (parseResult.success) {
|
|
248
|
+
console.log('Parsed plan:', parseResult.data);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Serialize APS to BMAD
|
|
252
|
+
const serializeResult = await adapter.serialize(apsPlan);
|
|
253
|
+
if (serializeResult.success) {
|
|
254
|
+
console.log('Generated BMAD:', serializeResult.content);
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### CLI Integration
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# Validate BMAD PRD
|
|
262
|
+
anvil validate docs/prd.md
|
|
263
|
+
# ✓ Detected format: bmad (100% confidence)
|
|
264
|
+
|
|
265
|
+
# Run quality gates on BMAD document
|
|
266
|
+
anvil gate docs/architecture.md
|
|
267
|
+
# ✓ All quality gates passed
|
|
268
|
+
|
|
269
|
+
# Convert BMAD to APS
|
|
270
|
+
anvil export docs/prd.md --to aps
|
|
271
|
+
# ✓ Export complete (6 functional requirements, 3 non-functional requirements)
|
|
272
|
+
|
|
273
|
+
# Roundtrip verification
|
|
274
|
+
# Parse → Serialize → Parse preserves document structure
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### APS Mapping
|
|
278
|
+
|
|
279
|
+
- **Functional Requirements (FR-XX)** → `proposed_changes[]` with type
|
|
280
|
+
`file_create` or `file_update`
|
|
281
|
+
- **Non-Functional Requirements (NFR-XX)** → `proposed_changes[]` with type
|
|
282
|
+
`config_update`
|
|
283
|
+
- **User Stories (US-XX)** → `proposed_changes[]` with acceptance criteria in
|
|
284
|
+
description
|
|
285
|
+
- **YAML Front-matter** → `provenance` (author, date, version)
|
|
286
|
+
- **Document Title/Summary** → `intent.description`
|
|
287
|
+
- **Change Log** → `metadata.changeLog[]`
|
|
288
|
+
|
|
289
|
+
#### Implementation Details
|
|
290
|
+
|
|
291
|
+
**Files**:
|
|
292
|
+
|
|
293
|
+
- `format-adapter.ts` - Main FormatAdapter implementation
|
|
294
|
+
- `parser.ts` - BMAD → APS conversion
|
|
295
|
+
- `serializer.ts` - APS → BMAD generation
|
|
296
|
+
- `types.ts` - BMAD-specific TypeScript types
|
|
297
|
+
- `utils.ts` - Helper functions (metadata extraction, requirement parsing)
|
|
298
|
+
|
|
299
|
+
**Registry Integration**:
|
|
300
|
+
|
|
301
|
+
- Auto-registered with `AdapterRegistry` on module import
|
|
302
|
+
- Discoverable by CLI's `FormatDetectionService`
|
|
303
|
+
|
|
304
|
+
**Validation**:
|
|
305
|
+
|
|
306
|
+
- Content validation without full parse
|
|
307
|
+
- Returns `ValidationIssue[]` with severity levels (error, warning, info)
|
|
308
|
+
- Checks format indicators and document structure
|
|
309
|
+
|
|
310
|
+
**Next Steps**:
|
|
311
|
+
|
|
312
|
+
- ✅ Comprehensive testing complete (86 tests, exceeding 50+ target)
|
|
313
|
+
- ✅ Test fixtures created (6 valid + invalid BMAD documents)
|
|
314
|
+
- ✅ Serves as reference implementation for FormatAdapter interface
|
|
315
|
+
|
|
316
|
+
### Generic Markdown ✅ COMPLETE
|
|
317
|
+
|
|
318
|
+
Fallback adapter for generic planning documents that don't match SpecKit or BMAD
|
|
319
|
+
formats. Provides broad compatibility for PRDs, TODOs, RFCs, and ADRs.
|
|
320
|
+
|
|
321
|
+
- **Extensions**: `.md` (PRD, TODO, plan, spec, RFC, ADR formats)
|
|
322
|
+
- **Status**: ✅ Fully implemented (November 2025)
|
|
323
|
+
- **Version**: 1.0.0
|
|
324
|
+
- **Code**: ~198 lines
|
|
325
|
+
- **Tests**: 32 tests (all passing ✅)
|
|
326
|
+
- **Coverage**: >95%
|
|
327
|
+
- **Detection**: Fallback adapter (30-45% confidence)
|
|
328
|
+
|
|
329
|
+
#### Supported Document Types
|
|
330
|
+
|
|
331
|
+
- **PRD (Product Requirements Document)** - Generic product requirements
|
|
332
|
+
- **TODO** - Task lists and action items
|
|
333
|
+
- **Plan** - Implementation plans
|
|
334
|
+
- **Spec** - Technical specifications
|
|
335
|
+
- **RFC (Request for Comments)** - Design proposals
|
|
336
|
+
- **ADR (Architecture Decision Records)** - Architecture decisions
|
|
337
|
+
|
|
338
|
+
#### Format Detection
|
|
339
|
+
|
|
340
|
+
Generic adapter uses fallback detection with lower confidence (30-45%):
|
|
341
|
+
|
|
342
|
+
- Generic markdown structure: 15 points
|
|
343
|
+
- Common planning keywords: 10 points
|
|
344
|
+
- Section headers (Requirements, Tasks, etc.): 10 points
|
|
345
|
+
- **Detection threshold**: 30%
|
|
346
|
+
- **Typical confidence**: 30-45% (intentionally lower than specific formats)
|
|
347
|
+
|
|
348
|
+
#### Usage Example
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { GenericMarkdownAdapter } from '@eddacraft/anvil-adapters/generic';
|
|
352
|
+
|
|
353
|
+
const adapter = new GenericMarkdownAdapter();
|
|
354
|
+
|
|
355
|
+
// Detect generic markdown
|
|
356
|
+
const detection = adapter.detect(content);
|
|
357
|
+
console.log(`Confidence: ${detection.confidence}%`);
|
|
358
|
+
|
|
359
|
+
// Parse generic markdown to APS
|
|
360
|
+
const parseResult = await adapter.parse(content);
|
|
361
|
+
if (parseResult.success) {
|
|
362
|
+
// Extracted requirements, tasks, features, goals
|
|
363
|
+
console.log('Parsed plan:', parseResult.data);
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### CLI Integration
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
# Validate generic TODO document
|
|
371
|
+
anvil validate TODO.md
|
|
372
|
+
# ✓ Detected format: generic (45% confidence)
|
|
373
|
+
|
|
374
|
+
# Run gates on generic RFC
|
|
375
|
+
anvil gate docs/RFC-001.md
|
|
376
|
+
# ✓ Format: generic markdown
|
|
377
|
+
|
|
378
|
+
# Works as fallback for unknown formats
|
|
379
|
+
anvil validate docs/custom-plan.md
|
|
380
|
+
# ✓ Falling back to generic markdown adapter
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
#### APS Mapping
|
|
384
|
+
|
|
385
|
+
- **Requirements sections** → `proposed_changes[]` with type `requirement`
|
|
386
|
+
- **Task lists** → `proposed_changes[]` with type `task`
|
|
387
|
+
- **Features** → `proposed_changes[]` with type `feature`
|
|
388
|
+
- **Goals/Objectives** → `intent.goals[]`
|
|
389
|
+
- **Document title** → `intent.description`
|
|
390
|
+
|
|
391
|
+
#### File Discovery Utility
|
|
392
|
+
|
|
393
|
+
Automatically finds planning documents in repositories:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
import { findPlanningDocuments } from '@eddacraft/anvil-adapters/utils';
|
|
397
|
+
|
|
398
|
+
// Search for planning docs in current directory
|
|
399
|
+
const docs = await findPlanningDocuments();
|
|
400
|
+
|
|
401
|
+
// Returns sorted by confidence and recency
|
|
402
|
+
docs.forEach((doc) => {
|
|
403
|
+
console.log(`${doc.path} - ${doc.pattern} (confidence: ${doc.confidence}%)`);
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// Example output:
|
|
407
|
+
// docs/prd.md - prd (high confidence)
|
|
408
|
+
// TODO.md - todo (medium confidence)
|
|
409
|
+
// docs/RFC-001.md - rfc (medium confidence)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Next Steps**:
|
|
413
|
+
|
|
414
|
+
- ✅ Generic adapter complete with full test coverage
|
|
415
|
+
- ✅ File discovery utility implemented
|
|
416
|
+
- ✅ Provides broad compatibility for any markdown planning document
|
|
417
|
+
|
|
418
|
+
## Development
|
|
419
|
+
|
|
420
|
+
### Running Tests
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
pnpm test # Run all tests (232 tests)
|
|
424
|
+
pnpm test:watch # Watch mode
|
|
425
|
+
pnpm test:coverage # Run with coverage report
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**Current Test Status** (as of November 2025):
|
|
429
|
+
|
|
430
|
+
- **Total: 232 tests** ✅ All passing
|
|
431
|
+
- SpecKit: 114 tests (45 format adapter + 69 parsers)
|
|
432
|
+
- BMAD: 86 tests (exceeds 50+ target)
|
|
433
|
+
- Generic: 32 tests
|
|
434
|
+
- **Coverage**: >95% across all adapters
|
|
435
|
+
|
|
436
|
+
### Type Checking
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
pnpm typecheck
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Building
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
npx nx build adapters
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Project Structure
|
|
449
|
+
|
|
450
|
+
```
|
|
451
|
+
packages/adapters/
|
|
452
|
+
├── src/
|
|
453
|
+
│ ├── base/ # Framework core (586 LOC)
|
|
454
|
+
│ │ ├── types.ts # FormatAdapter interface, base classes
|
|
455
|
+
│ │ ├── registry.ts # Adapter registry with detection
|
|
456
|
+
│ │ ├── utils.ts # Helper utilities
|
|
457
|
+
│ │ ├── testing.ts # Testing utilities
|
|
458
|
+
│ │ └── __tests__/
|
|
459
|
+
│ │ └── registry.test.ts # 22 tests (100% passing)
|
|
460
|
+
│ ├── common/ # Legacy adapter types (deprecated)
|
|
461
|
+
│ │ ├── types.ts # Old SpecToolAdapter interface
|
|
462
|
+
│ │ ├── registry.ts # Old registry implementation
|
|
463
|
+
│ │ └── index.ts
|
|
464
|
+
│ ├── speckit/ # SpecKit adapter (2,469 LOC)
|
|
465
|
+
│ │ ├── index.ts # Exports
|
|
466
|
+
│ │ ├── parser.ts # Core markdown parser (330 LOC)
|
|
467
|
+
│ │ ├── import.ts # V1 import adapter (284 LOC)
|
|
468
|
+
│ │ ├── import-v2.ts # V2 official format (424 LOC)
|
|
469
|
+
│ │ ├── export.ts # Export adapter (462 LOC)
|
|
470
|
+
│ │ └── parsers/ # Specialized parsers (966 LOC)
|
|
471
|
+
│ │ ├── spec-parser.ts # Spec.md parser (378 LOC)
|
|
472
|
+
│ │ ├── plan-parser.ts # Plan.md parser (342 LOC)
|
|
473
|
+
│ │ └── tasks-parser.ts # Tasks.md parser (246 LOC)
|
|
474
|
+
│ ├── __tests__/ # Test suite
|
|
475
|
+
│ │ ├── fixtures/ # Test fixtures
|
|
476
|
+
│ │ │ ├── speckit/ # Sample SpecKit documents
|
|
477
|
+
│ │ │ ├── speckit-official/ # Official spec-kit examples
|
|
478
|
+
│ │ │ └── aps/ # APS test fixtures
|
|
479
|
+
│ │ ├── speckit-import.test.ts # V1 import tests
|
|
480
|
+
│ │ ├── speckit-import-v2.test.ts # V2 import tests
|
|
481
|
+
│ │ ├── speckit-export.test.ts # Export tests
|
|
482
|
+
│ │ ├── speckit-parser.test.ts # Core parser tests
|
|
483
|
+
│ │ └── speckit-spec-parser.test.ts # Spec parser tests
|
|
484
|
+
│ └── index.ts # Main package exports
|
|
485
|
+
└── README.md # This file
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
## Design Principles
|
|
489
|
+
|
|
490
|
+
1. **Format Agnostic**: Users work with their preferred format
|
|
491
|
+
2. **APS Internal**: Validation and execution always use APS
|
|
492
|
+
3. **Round-trip Fidelity**: Parse → Serialize → Parse preserves intent
|
|
493
|
+
4. **Content Detection**: Auto-detect format from content
|
|
494
|
+
5. **Extensible**: Easy to add new format adapters
|
|
495
|
+
6. **Type Safe**: Full TypeScript support
|
|
496
|
+
|
|
497
|
+
## Licence
|
|
498
|
+
|
|
499
|
+
Copyright (c) 2026 EddaCraft. All rights reserved. See [LICENSE](../../LICENSE)
|
|
500
|
+
for details.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APS Markdown Format Adapter
|
|
3
|
+
*
|
|
4
|
+
* FormatAdapter implementation for Anvil Plan Spec (APS) markdown format.
|
|
5
|
+
* Handles both leaf specs (.aps.md with Tasks section) and index files
|
|
6
|
+
* (.aps.md with Modules section).
|
|
7
|
+
*/
|
|
8
|
+
import { type APSPlan, type ValidationResult } from '@eddacraft/anvil-core';
|
|
9
|
+
import { BaseFormatAdapter, type AdapterMetadata, type DetectionResult, type ParseResult, type SerializeResult, type ParseContext, type AdapterOptions } from '../base/types.js';
|
|
10
|
+
/**
|
|
11
|
+
* APS Markdown FormatAdapter implementation
|
|
12
|
+
*
|
|
13
|
+
* Converts between APS markdown documents and APS plans.
|
|
14
|
+
*/
|
|
15
|
+
export declare class APSMarkdownAdapter extends BaseFormatAdapter {
|
|
16
|
+
readonly metadata: AdapterMetadata;
|
|
17
|
+
/**
|
|
18
|
+
* Detect if content is APS markdown format
|
|
19
|
+
*
|
|
20
|
+
* Uses confidence scoring based on multiple indicators:
|
|
21
|
+
* - Tasks section with SCOPE-NNN headings (30 points)
|
|
22
|
+
* - **Intent:** field in tasks (20 points)
|
|
23
|
+
* - Modules section (25 points)
|
|
24
|
+
* - .aps.md path links (20 points)
|
|
25
|
+
* - **Scope:** field (10 points)
|
|
26
|
+
* - **Confidence:** field (10 points)
|
|
27
|
+
* - **Owner:** field (5 points)
|
|
28
|
+
* - **Priority:** field (5 points)
|
|
29
|
+
*
|
|
30
|
+
* @param content - Document content to analyze
|
|
31
|
+
* @returns Detection result with confidence score
|
|
32
|
+
*/
|
|
33
|
+
detect(content: string): DetectionResult;
|
|
34
|
+
/**
|
|
35
|
+
* Parse APS markdown content to APS plan
|
|
36
|
+
*
|
|
37
|
+
* Converts an APS markdown document (leaf spec) to an APSPlan execution schema.
|
|
38
|
+
* Each task in the document becomes a proposed change in the plan.
|
|
39
|
+
*
|
|
40
|
+
* @param content - APS markdown content
|
|
41
|
+
* @param context - Parse context for provenance
|
|
42
|
+
* @param _options - Adapter options
|
|
43
|
+
* @returns Parse result with APS plan
|
|
44
|
+
*/
|
|
45
|
+
parse(content: string, context?: ParseContext, _options?: AdapterOptions): Promise<ParseResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Convert a parsed document to an APSPlan
|
|
48
|
+
*/
|
|
49
|
+
private convertToAPSPlan;
|
|
50
|
+
/**
|
|
51
|
+
* Convert a task to a change object
|
|
52
|
+
*/
|
|
53
|
+
private taskToChange;
|
|
54
|
+
/**
|
|
55
|
+
* Infer the change type from task intent
|
|
56
|
+
*/
|
|
57
|
+
private inferChangeType;
|
|
58
|
+
/**
|
|
59
|
+
* Serialize APS plan to APS markdown format
|
|
60
|
+
*
|
|
61
|
+
* NOTE: Not yet implemented - returns NOT_IMPLEMENTED error.
|
|
62
|
+
*
|
|
63
|
+
* @param _plan - APS plan to serialize
|
|
64
|
+
* @param _options - Adapter options
|
|
65
|
+
* @returns Serialize result with APS markdown
|
|
66
|
+
*/
|
|
67
|
+
serialize(_plan: APSPlan, _options?: AdapterOptions): Promise<SerializeResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Validate APS markdown content
|
|
70
|
+
*
|
|
71
|
+
* NOTE: Not yet implemented - returns NOT_IMPLEMENTED error.
|
|
72
|
+
*
|
|
73
|
+
* @param _content - APS markdown content to validate
|
|
74
|
+
* @param _options - Validation options
|
|
75
|
+
* @returns Validation result
|
|
76
|
+
*/
|
|
77
|
+
validate(_content: string, _options?: AdapterOptions): Promise<ValidationResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Override canImport to handle the compound extension .aps.md
|
|
80
|
+
*/
|
|
81
|
+
canImport(format: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Analyze content for APS markdown indicators
|
|
84
|
+
*/
|
|
85
|
+
private analyzeContent;
|
|
86
|
+
/**
|
|
87
|
+
* Calculate confidence score based on indicators
|
|
88
|
+
*/
|
|
89
|
+
private calculateConfidence;
|
|
90
|
+
/**
|
|
91
|
+
* Build detection reason message
|
|
92
|
+
*/
|
|
93
|
+
private buildDetectionReason;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create a new APS markdown adapter instance
|
|
97
|
+
*
|
|
98
|
+
* @param options - Adapter options
|
|
99
|
+
* @returns APS markdown adapter instance
|
|
100
|
+
*/
|
|
101
|
+
export declare function createAPSMarkdownAdapter(options?: AdapterOptions): APSMarkdownAdapter;
|
|
102
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/aps-markdown/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,gBAAgB,EAKtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAmC1B;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,iBAAiB;IACvD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAOhC;IAEF;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe;IASxC;;;;;;;;;;OAUG;IACG,KAAK,CACT,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,EACtB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,WAAW,CAAC;IAevB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkCxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAsBpB;;OAEG;IACH,OAAO,CAAC,eAAe;IAmCvB;;;;;;;;OAQG;IACG,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IASpF;;;;;;;;OAQG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAetF;;OAEG;IACM,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAS3C;;OAEG;IACH,OAAO,CAAC,cAAc;IA0DtB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyD3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAoC7B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,kBAAkB,CAErF"}
|