speclore 0.1.1
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/LICENSE +21 -0
- package/README.en.md +240 -0
- package/README.md +240 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +5750 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/templates/report.html +201 -0
- package/dist/index.d.ts +505 -0
- package/dist/index.js +5744 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +4437 -0
- package/dist/mcp/server.js.map +1 -0
- package/package.json +107 -0
- package/scripts/cleanup-global.cjs +46 -0
- package/src/cli/templates/report.html +201 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>SpecLore Verification Report — {{PROJECT}}</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--color-bg: #f8f9fa;
|
|
10
|
+
--color-surface: #ffffff;
|
|
11
|
+
--color-text: #1a1a2e;
|
|
12
|
+
--color-text-secondary: #6c757d;
|
|
13
|
+
--color-border: #dee2e6;
|
|
14
|
+
--color-passed: #198754;
|
|
15
|
+
--color-failed: #dc3545;
|
|
16
|
+
--color-skipped: #ffc107;
|
|
17
|
+
--color-unmapped: #6c757d;
|
|
18
|
+
--color-accent: #0d6efd;
|
|
19
|
+
--radius: 8px;
|
|
20
|
+
}
|
|
21
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
22
|
+
body {
|
|
23
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
24
|
+
background: var(--color-bg);
|
|
25
|
+
color: var(--color-text);
|
|
26
|
+
line-height: 1.6;
|
|
27
|
+
padding: 2rem;
|
|
28
|
+
max-width: 1200px;
|
|
29
|
+
margin: 0 auto;
|
|
30
|
+
}
|
|
31
|
+
header {
|
|
32
|
+
background: var(--color-surface);
|
|
33
|
+
border: 1px solid var(--color-border);
|
|
34
|
+
border-radius: var(--radius);
|
|
35
|
+
padding: 1.5rem 2rem;
|
|
36
|
+
margin-bottom: 1.5rem;
|
|
37
|
+
}
|
|
38
|
+
header h1 {
|
|
39
|
+
font-size: 1.5rem;
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
margin-bottom: 0.5rem;
|
|
42
|
+
}
|
|
43
|
+
header .meta {
|
|
44
|
+
color: var(--color-text-secondary);
|
|
45
|
+
font-size: 0.875rem;
|
|
46
|
+
}
|
|
47
|
+
.summary {
|
|
48
|
+
display: grid;
|
|
49
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
50
|
+
gap: 1rem;
|
|
51
|
+
margin-bottom: 1.5rem;
|
|
52
|
+
}
|
|
53
|
+
.stat-card {
|
|
54
|
+
background: var(--color-surface);
|
|
55
|
+
border: 1px solid var(--color-border);
|
|
56
|
+
border-radius: var(--radius);
|
|
57
|
+
padding: 1rem 1.25rem;
|
|
58
|
+
text-align: center;
|
|
59
|
+
}
|
|
60
|
+
.stat-card .value {
|
|
61
|
+
font-size: 2rem;
|
|
62
|
+
font-weight: 700;
|
|
63
|
+
line-height: 1.2;
|
|
64
|
+
}
|
|
65
|
+
.stat-card .label {
|
|
66
|
+
font-size: 0.75rem;
|
|
67
|
+
text-transform: uppercase;
|
|
68
|
+
letter-spacing: 0.05em;
|
|
69
|
+
color: var(--color-text-secondary);
|
|
70
|
+
margin-top: 0.25rem;
|
|
71
|
+
}
|
|
72
|
+
.stat-card.passed .value { color: var(--color-passed); }
|
|
73
|
+
.stat-card.failed .value { color: var(--color-failed); }
|
|
74
|
+
.stat-card.unmapped .value { color: var(--color-unmapped); }
|
|
75
|
+
section.feature {
|
|
76
|
+
background: var(--color-surface);
|
|
77
|
+
border: 1px solid var(--color-border);
|
|
78
|
+
border-radius: var(--radius);
|
|
79
|
+
padding: 1.25rem 1.5rem;
|
|
80
|
+
margin-bottom: 1rem;
|
|
81
|
+
}
|
|
82
|
+
section.feature h3 {
|
|
83
|
+
font-size: 1.1rem;
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
margin-bottom: 0.25rem;
|
|
86
|
+
}
|
|
87
|
+
section.feature .file {
|
|
88
|
+
font-size: 0.8rem;
|
|
89
|
+
color: var(--color-text-secondary);
|
|
90
|
+
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
91
|
+
margin-bottom: 0.75rem;
|
|
92
|
+
}
|
|
93
|
+
table {
|
|
94
|
+
width: 100%;
|
|
95
|
+
border-collapse: collapse;
|
|
96
|
+
font-size: 0.875rem;
|
|
97
|
+
}
|
|
98
|
+
thead th {
|
|
99
|
+
text-align: left;
|
|
100
|
+
padding: 0.5rem 0.75rem;
|
|
101
|
+
border-bottom: 2px solid var(--color-border);
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
font-size: 0.75rem;
|
|
104
|
+
text-transform: uppercase;
|
|
105
|
+
letter-spacing: 0.05em;
|
|
106
|
+
color: var(--color-text-secondary);
|
|
107
|
+
}
|
|
108
|
+
tbody td {
|
|
109
|
+
padding: 0.5rem 0.75rem;
|
|
110
|
+
border-bottom: 1px solid var(--color-border);
|
|
111
|
+
}
|
|
112
|
+
.status {
|
|
113
|
+
display: inline-flex;
|
|
114
|
+
align-items: center;
|
|
115
|
+
gap: 0.25rem;
|
|
116
|
+
font-weight: 500;
|
|
117
|
+
font-size: 0.8rem;
|
|
118
|
+
padding: 0.15rem 0.5rem;
|
|
119
|
+
border-radius: 999px;
|
|
120
|
+
}
|
|
121
|
+
.status.passed { background: #d1e7dd; color: var(--color-passed); }
|
|
122
|
+
.status.failed { background: #f8d7da; color: var(--color-failed); }
|
|
123
|
+
.status.skipped { background: #fff3cd; color: #997404; }
|
|
124
|
+
.status.unmapped { background: #e2e3e5; color: var(--color-unmapped); }
|
|
125
|
+
section.failures {
|
|
126
|
+
background: var(--color-surface);
|
|
127
|
+
border: 1px solid #f8d7da;
|
|
128
|
+
border-radius: var(--radius);
|
|
129
|
+
padding: 1.25rem 1.5rem;
|
|
130
|
+
margin-top: 1.5rem;
|
|
131
|
+
}
|
|
132
|
+
section.failures h2 {
|
|
133
|
+
color: var(--color-failed);
|
|
134
|
+
font-size: 1.1rem;
|
|
135
|
+
margin-bottom: 0.75rem;
|
|
136
|
+
}
|
|
137
|
+
details {
|
|
138
|
+
margin-bottom: 0.75rem;
|
|
139
|
+
}
|
|
140
|
+
details summary {
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
font-weight: 500;
|
|
143
|
+
padding: 0.5rem 0;
|
|
144
|
+
color: var(--color-failed);
|
|
145
|
+
}
|
|
146
|
+
details pre {
|
|
147
|
+
background: #1e1e2e;
|
|
148
|
+
color: #cdd6f4;
|
|
149
|
+
padding: 1rem;
|
|
150
|
+
border-radius: var(--radius);
|
|
151
|
+
overflow-x: auto;
|
|
152
|
+
font-size: 0.8rem;
|
|
153
|
+
line-height: 1.5;
|
|
154
|
+
margin-top: 0.5rem;
|
|
155
|
+
}
|
|
156
|
+
footer {
|
|
157
|
+
text-align: center;
|
|
158
|
+
margin-top: 2rem;
|
|
159
|
+
color: var(--color-text-secondary);
|
|
160
|
+
font-size: 0.75rem;
|
|
161
|
+
}
|
|
162
|
+
</style>
|
|
163
|
+
</head>
|
|
164
|
+
<body>
|
|
165
|
+
<header>
|
|
166
|
+
<h1>SpecLore Verification Report</h1>
|
|
167
|
+
<p class="meta">{{PROJECT}} — {{TIMESTAMP}}</p>
|
|
168
|
+
</header>
|
|
169
|
+
|
|
170
|
+
<div class="summary">
|
|
171
|
+
<div class="stat-card">
|
|
172
|
+
<div class="value">{{TOTAL_SCENARIOS}}</div>
|
|
173
|
+
<div class="label">Total Scenarios</div>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="stat-card passed">
|
|
176
|
+
<div class="value">{{PASSED}}</div>
|
|
177
|
+
<div class="label">Passed</div>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="stat-card failed">
|
|
180
|
+
<div class="value">{{FAILED}}</div>
|
|
181
|
+
<div class="label">Failed</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="stat-card unmapped">
|
|
184
|
+
<div class="value">{{UNMAPPED}}</div>
|
|
185
|
+
<div class="label">Unmapped</div>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="stat-card">
|
|
188
|
+
<div class="value">{{PASS_RATE}}</div>
|
|
189
|
+
<div class="label">Pass Rate</div>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
{{FEATURES}}
|
|
194
|
+
|
|
195
|
+
{{FAILED_DETAILS}}
|
|
196
|
+
|
|
197
|
+
<footer>
|
|
198
|
+
Generated by <a href="https://github.com/nicepkg/speclore" style="color: var(--color-accent);">SpecLore</a>
|
|
199
|
+
</footer>
|
|
200
|
+
</body>
|
|
201
|
+
</html>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SpecLore CLI entry point.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* speclore — smart mode: show status + auto-action
|
|
6
|
+
* speclore "description" — one-liner to generate feature
|
|
7
|
+
* speclore setup — one-time project configuration
|
|
8
|
+
* speclore init — initialize project
|
|
9
|
+
* speclore status — project diagnostics
|
|
10
|
+
* speclore spec <source> — requirement → .feature
|
|
11
|
+
* speclore code — .feature → AI constraint files
|
|
12
|
+
* speclore verify — run tests → acceptance report
|
|
13
|
+
* speclore mcp — start MCP server (stdio)
|
|
14
|
+
* speclore teardown — uninstall cleanup
|
|
15
|
+
* speclore migrate — register existing .feature files into workflow state
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
declare function run(argv?: string[]): Promise<void>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* SpecLore configuration type definitions.
|
|
22
|
+
*
|
|
23
|
+
* Maps to `.speclore/config.yaml` structure.
|
|
24
|
+
* @module types/config
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** Root configuration — maps to config.yaml */
|
|
28
|
+
interface SpecLoreConfig {
|
|
29
|
+
project: ProjectConfig;
|
|
30
|
+
ai?: AIConfig;
|
|
31
|
+
spec: SpecConfig;
|
|
32
|
+
verify: VerifyConfig;
|
|
33
|
+
plugins?: PluginsConfig;
|
|
34
|
+
}
|
|
35
|
+
/** Project section */
|
|
36
|
+
interface ProjectConfig {
|
|
37
|
+
name: string;
|
|
38
|
+
language: string;
|
|
39
|
+
framework: string;
|
|
40
|
+
/** Profile level: strict | normal | minimal (default: normal) */
|
|
41
|
+
profile: ProfileLevel;
|
|
42
|
+
/** Module declarations */
|
|
43
|
+
modules: Record<string, ModuleConfig>;
|
|
44
|
+
}
|
|
45
|
+
/** Module declaration in config.yaml */
|
|
46
|
+
interface ModuleConfig {
|
|
47
|
+
path: string;
|
|
48
|
+
responsibility: string;
|
|
49
|
+
dependsOn?: string[];
|
|
50
|
+
entities?: string[];
|
|
51
|
+
apis?: string[];
|
|
52
|
+
}
|
|
53
|
+
/** AI provider section (optional — auto-detected when in AI client) */
|
|
54
|
+
interface AIConfig {
|
|
55
|
+
provider: 'openai-compatible' | 'claude' | 'ollama';
|
|
56
|
+
baseUrl?: string;
|
|
57
|
+
model?: string;
|
|
58
|
+
/** API key from environment variable name, default: SPECLORE_API_KEY */
|
|
59
|
+
apiKeyEnv?: string;
|
|
60
|
+
/** Maximum budget in USD — calls are rejected when exceeded */
|
|
61
|
+
maxBudgetUsd?: number;
|
|
62
|
+
/** Fallback providers tried in order when the primary is unavailable */
|
|
63
|
+
fallbackProviders?: AIConfig[];
|
|
64
|
+
}
|
|
65
|
+
/** Spec generation section */
|
|
66
|
+
interface SpecConfig {
|
|
67
|
+
/** Output directory for .feature files (default: "specs") */
|
|
68
|
+
outputDir: string;
|
|
69
|
+
/** Default language for generated features (default: "zh-CN") */
|
|
70
|
+
defaultLanguage: string;
|
|
71
|
+
/** Below this confidence, scenarios are flagged for review (default: 0.6) */
|
|
72
|
+
confidenceThreshold: number;
|
|
73
|
+
}
|
|
74
|
+
/** Verification section */
|
|
75
|
+
interface VerifyConfig {
|
|
76
|
+
/** Test command to execute */
|
|
77
|
+
command: string;
|
|
78
|
+
/** Test timeout in seconds (default: 300) */
|
|
79
|
+
timeout: number;
|
|
80
|
+
/** Report formats to generate (default: ["json", "html"]) */
|
|
81
|
+
reportFormat: ('json' | 'html')[];
|
|
82
|
+
/** Test-to-feature mapping rules */
|
|
83
|
+
mapping: MappingConfig;
|
|
84
|
+
}
|
|
85
|
+
/** Mapping configuration */
|
|
86
|
+
interface MappingConfig {
|
|
87
|
+
patterns: MappingPattern[];
|
|
88
|
+
}
|
|
89
|
+
/** Single mapping pattern */
|
|
90
|
+
interface MappingPattern {
|
|
91
|
+
/** Feature file pattern, e.g. "specs/{module}/{name}.feature" */
|
|
92
|
+
feature: string;
|
|
93
|
+
/** Test file pattern, e.g. "tests/{module}/{Name}Test.*" */
|
|
94
|
+
test: string;
|
|
95
|
+
}
|
|
96
|
+
/** Plugin registration section */
|
|
97
|
+
interface PluginsConfig {
|
|
98
|
+
readers?: PluginRef[];
|
|
99
|
+
writers?: PluginRef[];
|
|
100
|
+
parsers?: PluginRef[];
|
|
101
|
+
}
|
|
102
|
+
/** Plugin reference in config.yaml */
|
|
103
|
+
interface PluginRef {
|
|
104
|
+
name: string;
|
|
105
|
+
package: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* SpecLore core type definitions.
|
|
110
|
+
*
|
|
111
|
+
* This is the single source of truth for all data models.
|
|
112
|
+
* M1-M5 modules reference types defined here.
|
|
113
|
+
*
|
|
114
|
+
* @module types
|
|
115
|
+
*/
|
|
116
|
+
/** Structured requirement — M1 output */
|
|
117
|
+
interface StructuredRequirement {
|
|
118
|
+
/** File-path-derived ID, e.g. "order/create" */
|
|
119
|
+
id: string;
|
|
120
|
+
title: string;
|
|
121
|
+
description: string;
|
|
122
|
+
/** Original acceptance criteria (if present in source) */
|
|
123
|
+
acceptanceCriteria?: string[];
|
|
124
|
+
/** IDs of other features this one depends on */
|
|
125
|
+
dependencies?: string[];
|
|
126
|
+
/** Raw source content */
|
|
127
|
+
rawContent: string;
|
|
128
|
+
/** Parsing confidence score (0-1) */
|
|
129
|
+
confidence: number;
|
|
130
|
+
}
|
|
131
|
+
/** Feature file — M2 output */
|
|
132
|
+
interface FeatureFile {
|
|
133
|
+
path: string;
|
|
134
|
+
featureName: string;
|
|
135
|
+
scenarios: Scenario[];
|
|
136
|
+
tags: string[];
|
|
137
|
+
confidence: number;
|
|
138
|
+
/** Scenarios that need human review (low confidence) */
|
|
139
|
+
needsReview: string[];
|
|
140
|
+
}
|
|
141
|
+
/** BDD Scenario */
|
|
142
|
+
interface Scenario {
|
|
143
|
+
name: string;
|
|
144
|
+
givens: Step[];
|
|
145
|
+
whens: Step[];
|
|
146
|
+
thens: Step[];
|
|
147
|
+
tags: string[];
|
|
148
|
+
}
|
|
149
|
+
/** BDD Step */
|
|
150
|
+
interface Step {
|
|
151
|
+
keyword: 'Given' | 'When' | 'Then' | 'And' | 'But';
|
|
152
|
+
text: string;
|
|
153
|
+
}
|
|
154
|
+
/** Project context — M5 output */
|
|
155
|
+
interface ProjectContext {
|
|
156
|
+
language: string;
|
|
157
|
+
framework: string;
|
|
158
|
+
modules: ModuleGroup[];
|
|
159
|
+
dependencies: GraphEdge[];
|
|
160
|
+
existingEntities: EntityInfo[];
|
|
161
|
+
existingApis: ApiInfo[];
|
|
162
|
+
testFramework: string;
|
|
163
|
+
buildTool: string;
|
|
164
|
+
}
|
|
165
|
+
/** Module group */
|
|
166
|
+
interface ModuleGroup {
|
|
167
|
+
name: string;
|
|
168
|
+
path: string;
|
|
169
|
+
responsibility: string;
|
|
170
|
+
entities: string[];
|
|
171
|
+
apis: string[];
|
|
172
|
+
dependsOn: string[];
|
|
173
|
+
}
|
|
174
|
+
/** Dependency graph edge */
|
|
175
|
+
interface GraphEdge {
|
|
176
|
+
from: string;
|
|
177
|
+
to: string;
|
|
178
|
+
type: 'api-call' | 'event' | 'shared-entity' | 'import';
|
|
179
|
+
}
|
|
180
|
+
/** Module boundary — tells AI not to cross-module reference */
|
|
181
|
+
interface ModuleBoundary {
|
|
182
|
+
name: string;
|
|
183
|
+
responsibility: string;
|
|
184
|
+
/** APIs that other modules may call */
|
|
185
|
+
publicApis: string[];
|
|
186
|
+
/** Internal objects that other modules must NOT reference directly */
|
|
187
|
+
internalObjects: string[];
|
|
188
|
+
dependsOn: string[];
|
|
189
|
+
}
|
|
190
|
+
/** Entity info extracted from source code */
|
|
191
|
+
interface EntityInfo {
|
|
192
|
+
name: string;
|
|
193
|
+
module: string;
|
|
194
|
+
file: string;
|
|
195
|
+
}
|
|
196
|
+
/** API info extracted from source code */
|
|
197
|
+
interface ApiInfo {
|
|
198
|
+
method: string;
|
|
199
|
+
path: string;
|
|
200
|
+
module: string;
|
|
201
|
+
file: string;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Verification report — M4 output, persisted to `.speclore/reports/`.
|
|
205
|
+
* This is the single authoritative definition.
|
|
206
|
+
* VerifyMcpResult (MCP response) is a slim view of this.
|
|
207
|
+
*/
|
|
208
|
+
interface VerifyReport {
|
|
209
|
+
timestamp: string;
|
|
210
|
+
project: string;
|
|
211
|
+
summary: ReportSummary;
|
|
212
|
+
features: FeatureResult[];
|
|
213
|
+
failedDetails: FailedDetail[];
|
|
214
|
+
}
|
|
215
|
+
interface ReportSummary {
|
|
216
|
+
totalFeatures: number;
|
|
217
|
+
totalScenarios: number;
|
|
218
|
+
passed: number;
|
|
219
|
+
failed: number;
|
|
220
|
+
skipped: number;
|
|
221
|
+
/** Number of scenarios with no corresponding test */
|
|
222
|
+
unmapped: number;
|
|
223
|
+
/** e.g. "95.3%" */
|
|
224
|
+
passRate: string;
|
|
225
|
+
}
|
|
226
|
+
interface FeatureResult {
|
|
227
|
+
/** Feature name */
|
|
228
|
+
feature: string;
|
|
229
|
+
/** Feature file path */
|
|
230
|
+
file: string;
|
|
231
|
+
scenarios: ScenarioResult[];
|
|
232
|
+
}
|
|
233
|
+
interface ScenarioResult {
|
|
234
|
+
name: string;
|
|
235
|
+
status: 'passed' | 'failed' | 'skipped' | 'unmapped';
|
|
236
|
+
duration?: string;
|
|
237
|
+
/** Mapped test file */
|
|
238
|
+
testFile?: string;
|
|
239
|
+
/** Mapped test method name */
|
|
240
|
+
testMethod?: string;
|
|
241
|
+
/** How the mapping was resolved */
|
|
242
|
+
mappingSource?: 'mapping-file' | 'tag' | 'none';
|
|
243
|
+
/** Error message when status is 'failed' */
|
|
244
|
+
error?: string;
|
|
245
|
+
}
|
|
246
|
+
interface FailedDetail {
|
|
247
|
+
feature: string;
|
|
248
|
+
scenario: string;
|
|
249
|
+
/** Test error message */
|
|
250
|
+
error: string;
|
|
251
|
+
/** AI-generated fix suggestion */
|
|
252
|
+
suggestion?: string;
|
|
253
|
+
}
|
|
254
|
+
/** Module-level rule — element type of ConstraintResult.moduleRules */
|
|
255
|
+
interface ModuleRule {
|
|
256
|
+
/** Module name, e.g. "order" */
|
|
257
|
+
module: string;
|
|
258
|
+
boundaries: ModuleBoundary;
|
|
259
|
+
/** e.g. ["Entity suffix denotes domain entity", "Service suffix denotes application service"] */
|
|
260
|
+
namingConventions: string[];
|
|
261
|
+
/** e.g. ["Controllers must not contain business logic"] */
|
|
262
|
+
forbiddenPatterns: string[];
|
|
263
|
+
}
|
|
264
|
+
/** Serialized ProjectContext with metadata */
|
|
265
|
+
interface ContextFile {
|
|
266
|
+
/** Context schema version, e.g. "1.0" */
|
|
267
|
+
version: string;
|
|
268
|
+
/** ISO 8601 timestamp */
|
|
269
|
+
generatedAt: string;
|
|
270
|
+
/** e.g. "speclore v0.1.0" */
|
|
271
|
+
generatedBy: string;
|
|
272
|
+
/** Project structure summary (for AI to understand code organization) */
|
|
273
|
+
projectSummary: {
|
|
274
|
+
language: string;
|
|
275
|
+
framework: string;
|
|
276
|
+
buildTool: string;
|
|
277
|
+
testFramework: string;
|
|
278
|
+
/** Human-readable directory structure summary (≤ 50 lines) */
|
|
279
|
+
directoryStructure: string;
|
|
280
|
+
};
|
|
281
|
+
/** Module boundary declarations (for AI to avoid cross-module references) */
|
|
282
|
+
moduleBoundaries: ModuleBoundary[];
|
|
283
|
+
/** Existing entities and APIs (for AI to avoid duplication) */
|
|
284
|
+
existingCode: {
|
|
285
|
+
entities: Array<{
|
|
286
|
+
name: string;
|
|
287
|
+
module: string;
|
|
288
|
+
file: string;
|
|
289
|
+
}>;
|
|
290
|
+
apis: Array<{
|
|
291
|
+
method: string;
|
|
292
|
+
path: string;
|
|
293
|
+
module: string;
|
|
294
|
+
file: string;
|
|
295
|
+
}>;
|
|
296
|
+
};
|
|
297
|
+
/** Dependency graph (for AI to understand inter-module call direction) */
|
|
298
|
+
dependencyGraph: GraphEdge[];
|
|
299
|
+
/**
|
|
300
|
+
* Change impact analysis (optional, filled by M7 advanced analysis engine).
|
|
301
|
+
* Generated when `speclore verify --impact` is run.
|
|
302
|
+
*/
|
|
303
|
+
impactAnalysis?: {
|
|
304
|
+
changedFiles: string[];
|
|
305
|
+
affectedModules: string[];
|
|
306
|
+
affectedFeatures: string[];
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/** Mapping file — AI generates alongside test code */
|
|
310
|
+
interface MappingFile {
|
|
311
|
+
/** Path to the feature file, e.g. "specs/order/create.feature" */
|
|
312
|
+
feature: string;
|
|
313
|
+
/** ISO 8601 timestamp */
|
|
314
|
+
generatedAt: string;
|
|
315
|
+
/** Scenario name → test mapping */
|
|
316
|
+
scenarios: Record<string, MappingEntry>;
|
|
317
|
+
}
|
|
318
|
+
/** Single scenario → test mapping */
|
|
319
|
+
interface MappingEntry {
|
|
320
|
+
testFile: string;
|
|
321
|
+
testMethod: string;
|
|
322
|
+
}
|
|
323
|
+
/** speclore.spec MCP response */
|
|
324
|
+
interface SpecResult {
|
|
325
|
+
createdFiles: string[];
|
|
326
|
+
scenarios: ScenarioSummary[];
|
|
327
|
+
constraints: string;
|
|
328
|
+
nextSteps: string;
|
|
329
|
+
workflow: WorkflowInfo;
|
|
330
|
+
}
|
|
331
|
+
interface ScenarioSummary {
|
|
332
|
+
feature: string;
|
|
333
|
+
name: string;
|
|
334
|
+
given: string[];
|
|
335
|
+
when: string[];
|
|
336
|
+
then: string[];
|
|
337
|
+
}
|
|
338
|
+
/** speclore.code MCP response */
|
|
339
|
+
interface ConstraintResult {
|
|
340
|
+
writtenFiles: string[];
|
|
341
|
+
constraintContent: string;
|
|
342
|
+
moduleRules: ModuleRule[];
|
|
343
|
+
activeConstraints: ActiveConstraint[];
|
|
344
|
+
/** Comprehensive coding guidance for AI (≤ 2000 chars) */
|
|
345
|
+
codingGuidance: string;
|
|
346
|
+
scaffoldFiles: ScaffoldResult[];
|
|
347
|
+
workflow: WorkflowInfo;
|
|
348
|
+
}
|
|
349
|
+
interface ActiveConstraint {
|
|
350
|
+
file: string;
|
|
351
|
+
scope: 'project' | 'feature';
|
|
352
|
+
/** Glob pattern, e.g. "** /order/**" */
|
|
353
|
+
appliesTo: string;
|
|
354
|
+
/** One-line summary (AI quickly judges relevance) */
|
|
355
|
+
summary: string;
|
|
356
|
+
}
|
|
357
|
+
/** speclore.verify MCP response — slim view of VerifyReport */
|
|
358
|
+
interface VerifyMcpResult {
|
|
359
|
+
/** e.g. "12/12 scenarios passed" */
|
|
360
|
+
summary: string;
|
|
361
|
+
passed: number;
|
|
362
|
+
failed: number;
|
|
363
|
+
unmapped: number;
|
|
364
|
+
details: FeatureResult[];
|
|
365
|
+
failedDetails: FailedDetail[];
|
|
366
|
+
workflow: WorkflowInfo;
|
|
367
|
+
}
|
|
368
|
+
/** Requirement reader plugin interface */
|
|
369
|
+
interface ReaderPlugin {
|
|
370
|
+
readonly name: string;
|
|
371
|
+
readonly supportedFormats: string[];
|
|
372
|
+
canRead(source: string): boolean;
|
|
373
|
+
read(source: string): Promise<StructuredRequirement[]>;
|
|
374
|
+
}
|
|
375
|
+
/** AI tool constraint writer plugin interface */
|
|
376
|
+
interface WriterPlugin {
|
|
377
|
+
readonly toolName: string;
|
|
378
|
+
readonly configFile: string;
|
|
379
|
+
detect(projectRoot: string): boolean;
|
|
380
|
+
write(constraints: ConstraintContent): Promise<void>;
|
|
381
|
+
remove(): Promise<void>;
|
|
382
|
+
}
|
|
383
|
+
/** Constraint content to be written by WriterPlugin */
|
|
384
|
+
interface ConstraintContent {
|
|
385
|
+
projectName: string;
|
|
386
|
+
/** Absolute path to the project root directory */
|
|
387
|
+
projectRoot: string;
|
|
388
|
+
modules: ModuleRule[];
|
|
389
|
+
features: FeatureFile[];
|
|
390
|
+
profile: ProfileLevel;
|
|
391
|
+
/** Mapping rule instructions for AI */
|
|
392
|
+
mappingInstructions: string;
|
|
393
|
+
/** Feature business rules extracted from scenarios */
|
|
394
|
+
featureRules: FeatureRule[];
|
|
395
|
+
/** Test scaffolding info (optional) */
|
|
396
|
+
scaffoldInfo?: ScaffoldResult[];
|
|
397
|
+
}
|
|
398
|
+
/** Test result parser plugin interface */
|
|
399
|
+
interface ParserPlugin {
|
|
400
|
+
readonly framework: string;
|
|
401
|
+
canParse(testOutput: string): boolean;
|
|
402
|
+
parse(testOutput: string, features: FeatureFile[]): ScenarioResult[];
|
|
403
|
+
}
|
|
404
|
+
/** Supported AI tool identifiers */
|
|
405
|
+
type AITool = 'cursor' | 'claude' | 'qoder';
|
|
406
|
+
/** AI tool detection result */
|
|
407
|
+
interface AIToolInfo {
|
|
408
|
+
tool: AITool;
|
|
409
|
+
detected: boolean;
|
|
410
|
+
/** Config file paths that were found */
|
|
411
|
+
configFiles: string[];
|
|
412
|
+
}
|
|
413
|
+
/** Installation mode detection result */
|
|
414
|
+
interface InstallInfo {
|
|
415
|
+
mode: 'npm' | 'clone';
|
|
416
|
+
version: string;
|
|
417
|
+
/** Local path for clone mode */
|
|
418
|
+
localPath?: string;
|
|
419
|
+
}
|
|
420
|
+
/** Feature lifecycle state */
|
|
421
|
+
type FeatureState = 'specified' | 'constrained' | 'coding' | 'verified';
|
|
422
|
+
/** Project-wide state persisted to .speclore/state.yaml */
|
|
423
|
+
interface ProjectState {
|
|
424
|
+
schemaVersion: 1;
|
|
425
|
+
initialized: boolean;
|
|
426
|
+
initializedAt?: string;
|
|
427
|
+
features: Record<string, FeatureStateEntry>;
|
|
428
|
+
}
|
|
429
|
+
/** Per-feature state tracking */
|
|
430
|
+
interface FeatureStateEntry {
|
|
431
|
+
featureFile: string;
|
|
432
|
+
state: FeatureState;
|
|
433
|
+
constraintFiles: string[];
|
|
434
|
+
testFiles: string[];
|
|
435
|
+
lastStateChange: string;
|
|
436
|
+
lastVerify?: {
|
|
437
|
+
timestamp: string;
|
|
438
|
+
passed: number;
|
|
439
|
+
failed: number;
|
|
440
|
+
unmapped: number;
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
/** Workflow info appended to every MCP tool response */
|
|
444
|
+
interface WorkflowInfo {
|
|
445
|
+
feature?: string;
|
|
446
|
+
currentState: FeatureState | 'uninitialized';
|
|
447
|
+
nextStep: string;
|
|
448
|
+
projectSummary: {
|
|
449
|
+
total: number;
|
|
450
|
+
specified: number;
|
|
451
|
+
constrained: number;
|
|
452
|
+
coding: number;
|
|
453
|
+
verified: number;
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/** speclore.status MCP response */
|
|
457
|
+
interface StatusResult {
|
|
458
|
+
project: {
|
|
459
|
+
initialized: boolean;
|
|
460
|
+
configCreated: boolean;
|
|
461
|
+
testCommand: string;
|
|
462
|
+
aiToolsDetected: string[];
|
|
463
|
+
};
|
|
464
|
+
features: Array<{
|
|
465
|
+
file: string;
|
|
466
|
+
state: FeatureState;
|
|
467
|
+
scenarios: number;
|
|
468
|
+
constraintFiles: string[];
|
|
469
|
+
testFiles: string[];
|
|
470
|
+
lastVerify?: {
|
|
471
|
+
passed: number;
|
|
472
|
+
failed: number;
|
|
473
|
+
timestamp: string;
|
|
474
|
+
};
|
|
475
|
+
}>;
|
|
476
|
+
summary: {
|
|
477
|
+
total: number;
|
|
478
|
+
specified: number;
|
|
479
|
+
constrained: number;
|
|
480
|
+
coding: number;
|
|
481
|
+
verified: number;
|
|
482
|
+
};
|
|
483
|
+
recommendedActions: string[];
|
|
484
|
+
}
|
|
485
|
+
/** Test scaffolding generation result */
|
|
486
|
+
interface ScaffoldResult {
|
|
487
|
+
testFile: string;
|
|
488
|
+
framework: string;
|
|
489
|
+
scenarios: number;
|
|
490
|
+
}
|
|
491
|
+
/** Feature business rule extracted from scenarios */
|
|
492
|
+
interface FeatureRule {
|
|
493
|
+
featureName: string;
|
|
494
|
+
sourceFile: string;
|
|
495
|
+
scenarios: Array<{
|
|
496
|
+
name: string;
|
|
497
|
+
summary: string;
|
|
498
|
+
}>;
|
|
499
|
+
}
|
|
500
|
+
/** Profile level — controls constraint/detail granularity */
|
|
501
|
+
type ProfileLevel = 'strict' | 'normal' | 'minimal';
|
|
502
|
+
/** Log level */
|
|
503
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
504
|
+
|
|
505
|
+
export { type AIConfig, type AITool, type AIToolInfo, type ActiveConstraint, type ApiInfo, type ConstraintContent, type ConstraintResult, type ContextFile, type EntityInfo, type FailedDetail, type FeatureFile, type FeatureResult, type FeatureRule, type FeatureState, type FeatureStateEntry, type GraphEdge, type InstallInfo, type LogLevel, type MappingConfig, type MappingEntry, type MappingFile, type MappingPattern, type ModuleBoundary, type ModuleConfig, type ModuleGroup, type ModuleRule, type ParserPlugin, type PluginRef, type PluginsConfig, type ProfileLevel, type ProjectConfig, type ProjectContext, type ProjectState, type ReaderPlugin, type ReportSummary, type ScaffoldResult, type Scenario, type ScenarioResult, type ScenarioSummary, type SpecConfig, type SpecLoreConfig, type SpecResult, type StatusResult, type Step, type StructuredRequirement, type VerifyConfig, type VerifyMcpResult, type VerifyReport, type WorkflowInfo, type WriterPlugin, run };
|