@superkou/openspec 1.4.2 → 1.4.3

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.
@@ -31,18 +31,24 @@ export interface ValidationResult {
31
31
  /**
32
32
  * Validates that a change name follows kebab-case conventions.
33
33
  *
34
- * Valid names:
35
- * - Start with a lowercase letter
34
+ * Valid names (two accepted forms):
35
+ * - Classic kebab-case: starts with a lowercase letter
36
+ * (e.g., `add-auth`, `refactor-db`)
37
+ * - MMDD-prefixed kebab-case: starts with a 4-digit date (MMDD) followed by `-`
38
+ * and a kebab-case suffix (e.g., `0628-add-auth`)
39
+ *
40
+ * Both forms:
36
41
  * - Contain only lowercase letters, numbers, and hyphens
37
- * - Do not start or end with a hyphen
42
+ * - Do not start or end with a hyphen (the MMDD prefix's hyphen is part of the prefix)
38
43
  * - Do not contain consecutive hyphens
39
44
  *
40
45
  * @param name - The change name to validate
41
46
  * @returns Validation result with `valid: true` or `valid: false` with an error message
42
47
  *
43
48
  * @example
44
- * validateChangeName('add-auth') // { valid: true }
45
- * validateChangeName('Add-Auth') // { valid: false, error: '...' }
49
+ * validateChangeName('add-auth') // { valid: true }
50
+ * validateChangeName('0628-add-auth') // { valid: true }
51
+ * validateChangeName('Add-Auth') // { valid: false, error: '...' }
46
52
  */
47
53
  export declare function validateChangeName(name: string): ValidationResult;
48
54
  /**
@@ -6,23 +6,30 @@ const DEFAULT_SCHEMA = 'spec-driven';
6
6
  /**
7
7
  * Validates that a change name follows kebab-case conventions.
8
8
  *
9
- * Valid names:
10
- * - Start with a lowercase letter
9
+ * Valid names (two accepted forms):
10
+ * - Classic kebab-case: starts with a lowercase letter
11
+ * (e.g., `add-auth`, `refactor-db`)
12
+ * - MMDD-prefixed kebab-case: starts with a 4-digit date (MMDD) followed by `-`
13
+ * and a kebab-case suffix (e.g., `0628-add-auth`)
14
+ *
15
+ * Both forms:
11
16
  * - Contain only lowercase letters, numbers, and hyphens
12
- * - Do not start or end with a hyphen
17
+ * - Do not start or end with a hyphen (the MMDD prefix's hyphen is part of the prefix)
13
18
  * - Do not contain consecutive hyphens
14
19
  *
15
20
  * @param name - The change name to validate
16
21
  * @returns Validation result with `valid: true` or `valid: false` with an error message
17
22
  *
18
23
  * @example
19
- * validateChangeName('add-auth') // { valid: true }
20
- * validateChangeName('Add-Auth') // { valid: false, error: '...' }
24
+ * validateChangeName('add-auth') // { valid: true }
25
+ * validateChangeName('0628-add-auth') // { valid: true }
26
+ * validateChangeName('Add-Auth') // { valid: false, error: '...' }
21
27
  */
22
28
  export function validateChangeName(name) {
23
- // Pattern: starts with lowercase letter, followed by lowercase letters/numbers,
24
- // optionally followed by hyphen + lowercase letters/numbers (repeatable)
25
- const kebabCasePattern = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
29
+ // Pattern: two accepted forms.
30
+ // Form 1 (classic): ^[a-z][a-z0-9]*(-[a-z0-9]+)*$
31
+ // Form 2 (MMDD-prefixed): ^\d{4}-[a-z][a-z0-9]*(-[a-z0-9]+)*$
32
+ const kebabCasePattern = /^(?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*|\d{4}-[a-z][a-z0-9]*(?:-[a-z0-9]+)*)$/;
26
33
  if (!name) {
27
34
  return { valid: false, error: 'Change name cannot be empty' };
28
35
  }
@@ -49,10 +56,14 @@ export function validateChangeName(name) {
49
56
  if (/[^a-z0-9-]/.test(name)) {
50
57
  return { valid: false, error: 'Change name can only contain lowercase letters, numbers, and hyphens' };
51
58
  }
52
- if (/^[0-9]/.test(name)) {
53
- return { valid: false, error: 'Change name must start with a letter' };
59
+ // Numeric-prefixed name that didn't match Form 2: diagnose the date prefix shape
60
+ if (/^\d/.test(name)) {
61
+ if (!/^\d{4}-[a-z]/.test(name)) {
62
+ return { valid: false, error: 'Numeric-prefixed change name must use MMDD-<kebab> form (e.g., 0628-add-auth)' };
63
+ }
64
+ return { valid: false, error: 'Change name with MMDD prefix must be followed by kebab-case (e.g., 0628-add-auth)' };
54
65
  }
55
- return { valid: false, error: 'Change name must follow kebab-case convention (e.g., add-auth, refactor-db)' };
66
+ return { valid: false, error: 'Change name must follow kebab-case convention (e.g., add-auth, 0628-add-auth)' };
56
67
  }
57
68
  return { valid: true };
58
69
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superkou/openspec",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "AI-native system for spec-driven development",
5
5
  "keywords": [
6
6
  "openspec",
@@ -39,6 +39,24 @@
39
39
  "!dist/**/__tests__",
40
40
  "!dist/**/*.map"
41
41
  ],
42
+ "scripts": {
43
+ "lint": "eslint src/",
44
+ "build": "node build.js",
45
+ "dev": "tsc --watch",
46
+ "dev:cli": "pnpm build && node bin/openspec.js",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "test:ui": "vitest --ui",
50
+ "test:coverage": "vitest --coverage",
51
+ "test:postinstall": "node scripts/postinstall.js",
52
+ "prepare": "pnpm run build",
53
+ "prepublishOnly": "pnpm run build",
54
+ "postinstall": "node scripts/postinstall.js",
55
+ "check:pack-version": "node scripts/pack-version-check.mjs",
56
+ "release": "pnpm run release:ci",
57
+ "release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
58
+ "changeset": "changeset"
59
+ },
42
60
  "engines": {
43
61
  "node": ">=20.19.0"
44
62
  },
@@ -63,21 +81,5 @@
63
81
  "posthog-node": "^5.20.0",
64
82
  "yaml": "^2.8.2",
65
83
  "zod": "^4.0.17"
66
- },
67
- "scripts": {
68
- "lint": "eslint src/",
69
- "build": "node build.js",
70
- "dev": "tsc --watch",
71
- "dev:cli": "pnpm build && node bin/openspec.js",
72
- "test": "vitest run",
73
- "test:watch": "vitest",
74
- "test:ui": "vitest --ui",
75
- "test:coverage": "vitest --coverage",
76
- "test:postinstall": "node scripts/postinstall.js",
77
- "postinstall": "node scripts/postinstall.js",
78
- "check:pack-version": "node scripts/pack-version-check.mjs",
79
- "release": "pnpm run release:ci",
80
- "release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
81
- "changeset": "changeset"
82
84
  }
83
- }
85
+ }
@@ -1,3 +1,8 @@
1
+ <!--
2
+ 命名约定:change 目录名用 MMDD-<kebab> 前缀(如 0628-add-auth),便于按日期排序与追溯。
3
+ 校验已支持两种形式:经典 kebab(add-auth)与 MMDD- 前缀(0628-add-auth),优先用后者。
4
+ -->
5
+
1
6
  ## Why
2
7
 
3
8
  <!-- 说明此变更的动机。解决什么问题?为什么现在做? -->
@@ -9,13 +14,17 @@
9
14
  ## Capabilities
10
15
 
11
16
  ### New Capabilities
12
- <!-- 引入的新能力。将 <name> 替换为 kebab-case 标识符(例如 user-auth、data-export、api-rate-limiting)。每个将创建 specs/<name>/spec.md -->
17
+ <!--
18
+ 引入的新能力。将 <name> 替换为 kebab-case 标识符(例如 user-auth、data-export、api-rate-limiting)。每个将创建 specs/<name>/spec.md
19
+ -->
13
20
  - `<name>`: <此能力覆盖范围的简要描述>
14
21
 
15
22
  ### Modified Capabilities
16
- <!-- 需求发生变化的既有能力(不涉及实现细节)。
17
- 仅当 spec 级别行为变化时列出。每个需要 delta spec 文件。
18
- 使用 openspec/specs/ 中的既有 spec 名称。如无需求变更则留空。 -->
23
+ <!--
24
+ 需求发生变化的既有能力(不涉及实现细节)。
25
+ 仅当 spec 级别行为变化时列出。每个需要 delta spec 文件。
26
+ 使用 openspec/specs/ 中的既有 spec 名称。如无需求变更则留空。
27
+ -->
19
28
  - `<existing-name>`: <哪些需求正在变化>
20
29
 
21
30
  ## Impact