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/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "speclore",
3
+ "version": "0.1.1",
4
+ "description": "AI-powered CLI for BDD specs, coding constraints & acceptance testing. MCP-native.",
5
+ "keywords": [
6
+ "ai",
7
+ "ai-coding",
8
+ "bdd",
9
+ "gherkin",
10
+ "cucumber",
11
+ "mcp",
12
+ "mcp-server",
13
+ "cursor",
14
+ "claude-code",
15
+ "qoder",
16
+ "specification",
17
+ "acceptance-testing",
18
+ "test-automation",
19
+ "requirement-management",
20
+ "ai-constraints"
21
+ ],
22
+ "homepage": "https://github.com/cheneyzhang93/speclore#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/cheneyzhang93/speclore/issues"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/cheneyzhang93/speclore.git"
29
+ },
30
+ "license": "MIT",
31
+ "author": "Cheney",
32
+ "type": "module",
33
+ "exports": {
34
+ ".": {
35
+ "import": "./dist/index.js",
36
+ "types": "./dist/index.d.ts"
37
+ }
38
+ },
39
+ "main": "dist/index.js",
40
+ "module": "dist/index.js",
41
+ "types": "dist/index.d.ts",
42
+ "bin": {
43
+ "speclore": "dist/cli/index.js"
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "src/cli/templates",
48
+ "scripts",
49
+ "README.md",
50
+ "LICENSE"
51
+ ],
52
+ "scripts": {
53
+ "build": "node -e \"const p=require('path');const{execSync}=require('child_process');try{if(process.platform==='win32'){execSync('cmd /c rd /s /q dist',{stdio:'ignore'})}else{execSync('rm -rf dist',{stdio:'ignore'})}}catch(e){}\" && tsup && node -e \"require('fs').cpSync('src/cli/templates','dist/cli/templates',{recursive:true})\"",
54
+ "dev": "tsup --watch",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest",
57
+ "test:coverage": "vitest run --coverage",
58
+ "lint": "eslint src/",
59
+ "lint:fix": "eslint src/ --fix",
60
+ "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
61
+ "format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
62
+ "typecheck": "tsc --noEmit",
63
+ "prepublishOnly": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build",
64
+ "postuninstall": "node scripts/cleanup-global.cjs"
65
+ },
66
+ "dependencies": {
67
+ "@anthropic-ai/sdk": "^0.39.0",
68
+ "@cucumber/gherkin": "^30.0.0",
69
+ "@cucumber/messages": "^27.0.0",
70
+ "@modelcontextprotocol/sdk": "^1.12.0",
71
+ "chokidar": "^4.0.3",
72
+ "commander": "^13.1.0",
73
+ "exceljs": "^4.4.0",
74
+ "glob": "^11.0.1",
75
+ "inquirer": "^12.5.0",
76
+ "js-yaml": "^4.1.0",
77
+ "mammoth": "^1.8.0",
78
+ "openai": "^4.86.0",
79
+ "ora": "^8.2.0",
80
+ "pdf-parse": "^1.1.1",
81
+ "pino": "^10.3.1",
82
+ "pino-pretty": "^13.1.3",
83
+ "zod": "^4.4.3"
84
+ },
85
+ "devDependencies": {
86
+ "@eslint/js": "^9.25.0",
87
+ "@types/inquirer": "^9.0.7",
88
+ "@types/js-yaml": "^4.0.9",
89
+ "@types/node": "^22.15.0",
90
+ "@types/pdf-parse": "^1.1.4",
91
+ "@vitest/coverage-v8": "^3.1.0",
92
+ "eslint": "^9.25.0",
93
+ "prettier": "^3.5.3",
94
+ "tsup": "^8.4.0",
95
+ "typescript": "^5.8.3",
96
+ "typescript-eslint": "^8.30.0",
97
+ "vitest": "^3.1.0"
98
+ },
99
+ "engines": {
100
+ "node": ">=18.0.0"
101
+ },
102
+ "packageManager": "pnpm@10.8.0",
103
+ "publishConfig": {
104
+ "access": "public",
105
+ "registry": "https://registry.npmjs.org/"
106
+ }
107
+ }
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * npm postuninstall hook — cleans up SpecLore global cache files.
5
+ *
6
+ * When the user runs `npm uninstall -g speclore`, this script:
7
+ * 1. Detects if ~/.speclore/ exists
8
+ * 2. Removes only cache/runtime files (context.json, .lock, reports/, mappings/)
9
+ * 3. Preserves user customizations (config.yaml, etc.)
10
+ * 4. Runs silently — never blocks uninstall
11
+ *
12
+ * NOTE: This file uses CJS because the package declares "type": "module".
13
+ * The .cjs extension forces Node.js to interpret it as CommonJS.
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const os = require('os');
21
+
22
+ function cleanup() {
23
+ try {
24
+ const globalDir = path.join(os.homedir(), '.speclore');
25
+
26
+ if (!fs.existsSync(globalDir)) {
27
+ return; // Nothing to clean
28
+ }
29
+
30
+ // Only remove cache/runtime files, preserve user config (e.g. config.yaml)
31
+ const targets = ['context.json', '.lock', 'reports', 'mappings'];
32
+
33
+ for (const target of targets) {
34
+ const targetPath = path.join(globalDir, target);
35
+ try {
36
+ fs.rmSync(targetPath, { recursive: true, force: true });
37
+ } catch {
38
+ // Silently ignore individual failures — never block uninstall
39
+ }
40
+ }
41
+ } catch {
42
+ // Silently ignore — never block uninstall
43
+ }
44
+ }
45
+
46
+ cleanup();
@@ -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}} &mdash; {{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>