@planu/cli 4.6.0 → 4.6.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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [4.6.1] - 2026-06-12
2
+
3
+ ### Bug Fixes
4
+ - fix(SPEC-1086): handle Vitest 4 JSON paths in validate
5
+
6
+
1
7
  ## [4.6.0] - 2026-06-11
2
8
 
3
9
  ### Features
@@ -160,6 +160,23 @@ function runVitest(testPaths, projectPath, timeoutMs = 120_000) {
160
160
  });
161
161
  });
162
162
  }
163
+ function resolveVitestTestFilePath(result) {
164
+ // Vitest JSON returns the file path under `testResults[].name` in v4.
165
+ const candidates = [result.testFilePath, result.name, result.filepath, result.filePath];
166
+ for (const candidate of candidates) {
167
+ if (typeof candidate === 'string' && candidate.trim().length > 0) {
168
+ return candidate;
169
+ }
170
+ }
171
+ return null;
172
+ }
173
+ function toProjectRelativeTestPath(testFilePath, projectPath) {
174
+ const prefix = projectPath.endsWith('/') ? projectPath : `${projectPath}/`;
175
+ return testFilePath.startsWith(prefix) ? testFilePath.slice(prefix.length) : testFilePath;
176
+ }
177
+ function resolveScenarioTestPath(link) {
178
+ return typeof link.path === 'string' && link.path.trim().length > 0 ? link.path : null;
179
+ }
163
180
  // ---------------------------------------------------------------------------
164
181
  // Public API
165
182
  // ---------------------------------------------------------------------------
@@ -186,7 +203,10 @@ export async function runSpecCompliance(spec, projectPath) {
186
203
  const allTestPaths = new Set();
187
204
  for (const scenario of scenarios) {
188
205
  for (const link of scenario.tests ?? []) {
189
- allTestPaths.add(link.path);
206
+ const linkPath = resolveScenarioTestPath(link);
207
+ if (linkPath) {
208
+ allTestPaths.add(linkPath);
209
+ }
190
210
  }
191
211
  }
192
212
  const command = allTestPaths.size > 0
@@ -214,10 +234,14 @@ export async function runSpecCompliance(spec, projectPath) {
214
234
  const testFileStatus = new Map();
215
235
  if (vitestResult) {
216
236
  for (const tr of vitestResult.testResults) {
237
+ const testFilePath = resolveVitestTestFilePath(tr);
238
+ if (!testFilePath) {
239
+ continue;
240
+ }
217
241
  const allPassed = tr.assertionResults.every((r) => r.status === 'passed');
218
- testFileStatus.set(tr.testFilePath, allPassed ? 'pass' : 'fail');
242
+ testFileStatus.set(testFilePath, allPassed ? 'pass' : 'fail');
219
243
  // Also index by relative path
220
- const relPath = tr.testFilePath.replace(projectPath + '/', '');
244
+ const relPath = toProjectRelativeTestPath(testFilePath, projectPath);
221
245
  testFileStatus.set(relPath, allPassed ? 'pass' : 'fail');
222
246
  }
223
247
  }
@@ -236,23 +260,29 @@ export async function runSpecCompliance(spec, projectPath) {
236
260
  // Check all links
237
261
  const verdicts = [];
238
262
  for (const link of links) {
239
- const exists = existenceMap.get(link.path) !== false;
263
+ const linkPath = resolveScenarioTestPath(link);
264
+ if (!linkPath) {
265
+ evidence.push('Malformed test link: missing path');
266
+ verdicts.push('missing');
267
+ continue;
268
+ }
269
+ const exists = existenceMap.get(linkPath) !== false;
240
270
  if (!exists) {
241
- evidence.push(`${link.path}: file not found`);
271
+ evidence.push(`${linkPath}: file not found`);
242
272
  verdicts.push('missing');
243
273
  continue;
244
274
  }
245
- const status = testFileStatus.get(link.path) ?? (vitestResult ? 'fail' : 'missing');
275
+ const status = testFileStatus.get(linkPath) ?? (vitestResult ? 'fail' : 'missing');
246
276
  if (status === 'pass') {
247
- evidence.push(`${link.path}: passed`);
277
+ evidence.push(`${linkPath}: passed`);
248
278
  verdicts.push('pass');
249
279
  }
250
280
  else if (status === 'missing') {
251
- evidence.push(`${link.path}: not found in vitest output`);
281
+ evidence.push(`${linkPath}: not found in vitest output`);
252
282
  verdicts.push('missing');
253
283
  }
254
284
  else {
255
- evidence.push(`${link.path}: failed`);
285
+ evidence.push(`${linkPath}: failed`);
256
286
  verdicts.push('fail');
257
287
  }
258
288
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planu/cli",
3
- "version": "4.6.0",
3
+ "version": "4.6.1",
4
4
  "description": "Planu — MCP Server for Spec Driven Development with native Rust acceleration for hot paths. Cross-platform (Linux/macOS/Windows, x64/arm64, glibc/musl).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,14 +34,14 @@
34
34
  "packageName": "@planu/core"
35
35
  },
36
36
  "optionalDependencies": {
37
- "@planu/core-darwin-arm64": "4.6.0",
38
- "@planu/core-darwin-x64": "4.6.0",
39
- "@planu/core-linux-arm64-gnu": "4.6.0",
40
- "@planu/core-linux-arm64-musl": "4.6.0",
41
- "@planu/core-linux-x64-gnu": "4.6.0",
42
- "@planu/core-linux-x64-musl": "4.6.0",
43
- "@planu/core-win32-arm64-msvc": "4.6.0",
44
- "@planu/core-win32-x64-msvc": "4.6.0"
37
+ "@planu/core-darwin-arm64": "4.6.1",
38
+ "@planu/core-darwin-x64": "4.6.1",
39
+ "@planu/core-linux-arm64-gnu": "4.6.1",
40
+ "@planu/core-linux-arm64-musl": "4.6.1",
41
+ "@planu/core-linux-x64-gnu": "4.6.1",
42
+ "@planu/core-linux-x64-musl": "4.6.1",
43
+ "@planu/core-win32-arm64-msvc": "4.6.1",
44
+ "@planu/core-win32-x64-msvc": "4.6.1"
45
45
  },
46
46
  "engines": {
47
47
  "node": ">=24.0.0"
package/planu-native.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dev.planu.native",
3
3
  "displayName": "Planu Native Lightweight Surface",
4
- "version": "4.6.0",
4
+ "version": "4.6.1",
5
5
  "packageName": "@planu/cli",
6
6
  "modes": {
7
7
  "lightweight": {
package/planu-plugin.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dev.planu.cli",
3
3
  "displayName": "Planu — Spec Driven Development",
4
4
  "description": "Manage software specs, estimations, and autonomous SDD workflows. Language-agnostic MCP server for Claude Code.",
5
- "version": "4.6.0",
5
+ "version": "4.6.1",
6
6
  "icon": "assets/plugin/icon.svg",
7
7
  "command": [
8
8
  "npx",