@outcomeeng/spx 0.3.1 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@outcomeeng/spx",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Developer CLI for code validation and session management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -51,8 +51,8 @@
51
51
  "publish:check": "pnpm run validate && pnpm run build && vitest run && pnpm run validate:published",
52
52
  "knip": "tsx src/cli.ts validation knip",
53
53
  "circular": "tsx src/cli.ts validation circular",
54
- "format": "prettier --write .",
55
- "format:check": "prettier --check .",
54
+ "format": "dprint fmt .",
55
+ "format:check": "dprint check .",
56
56
  "prepare": "lefthook install",
57
57
  "prepublishOnly": "pnpm run publish:check"
58
58
  },
@@ -65,41 +65,46 @@
65
65
  "author": "Outcome Engineering",
66
66
  "license": "MIT",
67
67
  "devDependencies": {
68
- "@faker-js/faker": "^10.2.0",
69
- "@types/eslint-config-prettier": "^6.11.3",
68
+ "@faker-js/faker": "^10.4.0",
70
69
  "@types/estree": "^1.0.8",
71
70
  "@types/madge": "^5.0.3",
72
- "@types/node": "^20.10.0",
73
- "@vitest/coverage-v8": "^4.0.18",
74
- "eslint": "^9.39.2",
75
- "eslint-config-prettier": "^10.1.8",
71
+ "@types/node": "^20.19.39",
72
+ "@vitest/coverage-v8": "^4.1.5",
73
+ "eslint": "^9.39.4",
76
74
  "eslint-plugin-import": "^2.32.0",
77
- "fast-check": "^4.5.3",
78
- "globals": "^17.0.0",
79
- "husky": "^9.1.7",
75
+ "fast-check": "^4.7.0",
76
+ "globals": "^17.5.0",
80
77
  "jsonc-parser": "^3.3.1",
81
- "knip": "^5.80.0",
82
- "lefthook": "^1.10.10",
83
- "prettier": "^3.7.4",
84
- "tsup": "^8.0.1",
78
+ "knip": "^5.88.1",
79
+ "lefthook": "^1.13.6",
80
+ "tsup": "^8.5.1",
85
81
  "tsx": "^4.21.0",
86
- "typescript": "^5.3.3",
87
- "typescript-eslint": "^8.51.0",
88
- "vitest": "^4.0.18"
82
+ "typescript": "^5.9.3",
83
+ "typescript-eslint": "^8.59.1",
84
+ "vitest": "^4.1.5"
89
85
  },
90
86
  "dependencies": {
91
- "@typescript-eslint/parser": "^8.59.0",
92
- "@typescript-eslint/visitor-keys": "^8.59.0",
87
+ "@typescript-eslint/parser": "^8.59.1",
88
+ "@typescript-eslint/visitor-keys": "^8.59.1",
93
89
  "chalk": "^5.6.2",
94
90
  "commander": "^11.1.0",
95
91
  "eslint-visitor-keys": "^5.0.1",
96
92
  "execa": "^9.6.1",
97
93
  "fast-xml-parser": "^5.7.2",
98
94
  "madge": "^8.0.0",
99
- "markdownlint-cli2": "^0.22.0",
95
+ "markdownlint-cli2": "^0.22.1",
100
96
  "markdownlint-rule-relative-links": "^5.1.0",
101
97
  "smol-toml": "^1.6.1",
102
- "yaml": "^2.8.2"
98
+ "yaml": "^2.8.3"
103
99
  },
104
- "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319"
100
+ "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319",
101
+ "pnpm": {
102
+ "ignoredBuiltDependencies": [
103
+ "esbuild",
104
+ "lefthook"
105
+ ],
106
+ "overrides": {
107
+ "vite": "8.0.10"
108
+ }
109
+ }
105
110
  }
@@ -1,60 +0,0 @@
1
- // src/scanner/validation.ts
2
- var MIN_BSP_NUMBER = 10;
3
- var MAX_BSP_NUMBER = 99;
4
- function isValidBSPNumber(n) {
5
- return n >= MIN_BSP_NUMBER && n <= MAX_BSP_NUMBER;
6
- }
7
- function validateBSPNumber(n) {
8
- if (!isValidBSPNumber(n)) {
9
- throw new Error(
10
- `BSP number must be between ${MIN_BSP_NUMBER} and ${MAX_BSP_NUMBER}, got ${n}`
11
- );
12
- }
13
- return n;
14
- }
15
-
16
- // src/scanner/patterns.ts
17
- var WORK_ITEM_PATTERN = /^(capability|feature|story)-(\d+)_([a-z][a-z0-9-]*)$/;
18
- function parseWorkItemName(dirName) {
19
- const match = WORK_ITEM_PATTERN.exec(dirName);
20
- if (!match) {
21
- throw new Error(
22
- `Invalid work item name: "${dirName}". Expected format: {kind}-{number}_{slug} (e.g., "capability-21_core-cli", "feature-21_pattern-matching")`
23
- );
24
- }
25
- const kind = match[1];
26
- const bspNumber = parseInt(match[2], 10);
27
- const slug = match[3];
28
- validateBSPNumber(bspNumber);
29
- const number = kind === "capability" ? bspNumber - 1 : bspNumber;
30
- return {
31
- kind,
32
- number,
33
- slug
34
- };
35
- }
36
-
37
- // src/types.ts
38
- var WORK_ITEM_KINDS = [
39
- "capability",
40
- "feature",
41
- "story"
42
- ];
43
- var LEAF_KIND = WORK_ITEM_KINDS.at(-1);
44
- var WORK_ITEM_STATUSES = [
45
- "OPEN",
46
- "IN_PROGRESS",
47
- "DONE"
48
- ];
49
-
50
- export {
51
- MIN_BSP_NUMBER,
52
- MAX_BSP_NUMBER,
53
- isValidBSPNumber,
54
- validateBSPNumber,
55
- parseWorkItemName,
56
- WORK_ITEM_KINDS,
57
- LEAF_KIND,
58
- WORK_ITEM_STATUSES
59
- };
60
- //# sourceMappingURL=chunk-BQLLI7GS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/scanner/validation.ts","../src/scanner/patterns.ts","../src/types.ts"],"sourcesContent":["/**\n * Validation functions for BSP (Behavior, Structure, Property) numbers\n */\n\n/**\n * BSP number range constants\n */\nexport const MIN_BSP_NUMBER = 10;\nexport const MAX_BSP_NUMBER = 99;\n\n/**\n * Check if a number is a valid BSP number\n *\n * @param n - Number to validate\n * @returns true if n is in range [10, 99], false otherwise\n *\n * @example\n * ```typescript\n * isValidBSPNumber(20) // true\n * isValidBSPNumber(9) // false\n * isValidBSPNumber(100) // false\n * ```\n */\nexport function isValidBSPNumber(n: number): boolean {\n return n >= MIN_BSP_NUMBER && n <= MAX_BSP_NUMBER;\n}\n\n/**\n * Validate a BSP number and throw if invalid\n *\n * @param n - Number to validate\n * @returns The validated number\n * @throws Error if the number is outside the valid range [10, 99]\n *\n * @example\n * ```typescript\n * validateBSPNumber(20) // returns 20\n * validateBSPNumber(5) // throws Error: \"BSP number must be between 10 and 99, got 5\"\n * ```\n */\nexport function validateBSPNumber(n: number): number {\n if (!isValidBSPNumber(n)) {\n throw new Error(\n `BSP number must be between ${MIN_BSP_NUMBER} and ${MAX_BSP_NUMBER}, got ${n}`,\n );\n }\n return n;\n}\n","/**\n * Pattern matching for work item directory names\n */\nimport type { WorkItem, WorkItemKind } from \"../types.js\";\nimport { validateBSPNumber } from \"./validation.js\";\n\n/**\n * Regex pattern for work item directory names\n * Format: {kind}-{number}_{slug}\n * - kind: capability, feature, or story\n * - number: BSP number (10-99)\n * - slug: kebab-case identifier (lowercase, hyphens only)\n */\nconst WORK_ITEM_PATTERN = /^(capability|feature|story)-(\\d+)_([a-z][a-z0-9-]*)$/;\n\n/**\n * Parse a work item directory name into structured data\n *\n * @param dirName - Directory name to parse\n * @returns Parsed work item with kind, number, and slug (path not included)\n * @throws Error if the directory name doesn't match the pattern or BSP number is invalid\n *\n * @example\n * ```typescript\n * parseWorkItemName(\"capability-21_core-cli\")\n * // Returns: { kind: \"capability\", number: 20, slug: \"core-cli\" }\n *\n * parseWorkItemName(\"feature-21_pattern-matching\")\n * // Returns: { kind: \"feature\", number: 21, slug: \"pattern-matching\" }\n * ```\n */\nexport function parseWorkItemName(dirName: string): Omit<WorkItem, \"path\"> {\n const match = WORK_ITEM_PATTERN.exec(dirName);\n\n if (!match) {\n throw new Error(\n `Invalid work item name: \"${dirName}\". Expected format: {kind}-{number}_{slug} `\n + `(e.g., \"capability-21_core-cli\", \"feature-21_pattern-matching\")`,\n );\n }\n\n const kind = match[1] as WorkItemKind;\n const bspNumber = parseInt(match[2], 10);\n const slug = match[3];\n\n // Validate BSP number range using validation module\n validateBSPNumber(bspNumber);\n\n // Capabilities use 0-indexed numbers (directory number - 1)\n // Features and stories use directory number as-is\n const number = kind === \"capability\" ? bspNumber - 1 : bspNumber;\n\n return {\n kind,\n number,\n slug,\n };\n}\n","/**\n * Core type definitions for spx\n */\n\n/**\n * Work item types in the spec hierarchy\n */\nexport type WorkItemKind = \"capability\" | \"feature\" | \"story\";\n\n/**\n * Ordered hierarchy of work item kinds (root to leaf)\n *\n * Used by both production code and tests to derive hierarchy structure.\n * Per ADR-21: Never hardcode kind names - derive from this constant.\n */\nexport const WORK_ITEM_KINDS: readonly WorkItemKind[] = [\n \"capability\",\n \"feature\",\n \"story\",\n] as const;\n\n/**\n * The leaf kind (actionable work items)\n *\n * Derived from WORK_ITEM_KINDS to ensure consistency if hierarchy changes.\n */\nexport const LEAF_KIND: WorkItemKind = WORK_ITEM_KINDS.at(-1)!;\n\n/**\n * Parsed work item structure\n */\nexport interface WorkItem {\n /** The type of work item */\n kind: WorkItemKind;\n /** BSP number (0-indexed for capabilities, as-is for features/stories) */\n number: number;\n /** URL-safe slug identifier */\n slug: string;\n /** Full filesystem path to work item directory */\n path: string;\n}\n\n/**\n * Directory entry from filesystem traversal\n */\nexport interface DirectoryEntry {\n /** Directory name (basename) */\n name: string;\n /** Full absolute path */\n path: string;\n /** Whether this is a directory */\n isDirectory: boolean;\n}\n\n/**\n * Work item status\n */\nexport type WorkItemStatus = \"OPEN\" | \"IN_PROGRESS\" | \"DONE\";\n\n/**\n * Ordered list of work item statuses\n *\n * Used by both production code and tests to derive status values.\n * Per ADR-21: Never hardcode status names - derive from this constant.\n */\nexport const WORK_ITEM_STATUSES: readonly WorkItemStatus[] = [\n \"OPEN\",\n \"IN_PROGRESS\",\n \"DONE\",\n] as const;\n"],"mappings":";AAOO,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AAevB,SAAS,iBAAiB,GAAoB;AACnD,SAAO,KAAK,kBAAkB,KAAK;AACrC;AAeO,SAAS,kBAAkB,GAAmB;AACnD,MAAI,CAAC,iBAAiB,CAAC,GAAG;AACxB,UAAM,IAAI;AAAA,MACR,8BAA8B,cAAc,QAAQ,cAAc,SAAS,CAAC;AAAA,IAC9E;AAAA,EACF;AACA,SAAO;AACT;;;AClCA,IAAM,oBAAoB;AAkBnB,SAAS,kBAAkB,SAAyC;AACzE,QAAM,QAAQ,kBAAkB,KAAK,OAAO;AAE5C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,4BAA4B,OAAO;AAAA,IAErC;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,CAAC;AACpB,QAAM,YAAY,SAAS,MAAM,CAAC,GAAG,EAAE;AACvC,QAAM,OAAO,MAAM,CAAC;AAGpB,oBAAkB,SAAS;AAI3B,QAAM,SAAS,SAAS,eAAe,YAAY,IAAI;AAEvD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC1CO,IAAM,kBAA2C;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AACF;AAOO,IAAM,YAA0B,gBAAgB,GAAG,EAAE;AAuCrD,IAAM,qBAAgD;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
package/dist/index.d.ts DELETED
@@ -1,116 +0,0 @@
1
- /**
2
- * Core type definitions for spx
3
- */
4
- /**
5
- * Work item types in the spec hierarchy
6
- */
7
- type WorkItemKind = "capability" | "feature" | "story";
8
- /**
9
- * Ordered hierarchy of work item kinds (root to leaf)
10
- *
11
- * Used by both production code and tests to derive hierarchy structure.
12
- * Per ADR-21: Never hardcode kind names - derive from this constant.
13
- */
14
- declare const WORK_ITEM_KINDS: readonly WorkItemKind[];
15
- /**
16
- * The leaf kind (actionable work items)
17
- *
18
- * Derived from WORK_ITEM_KINDS to ensure consistency if hierarchy changes.
19
- */
20
- declare const LEAF_KIND: WorkItemKind;
21
- /**
22
- * Parsed work item structure
23
- */
24
- interface WorkItem {
25
- /** The type of work item */
26
- kind: WorkItemKind;
27
- /** BSP number (0-indexed for capabilities, as-is for features/stories) */
28
- number: number;
29
- /** URL-safe slug identifier */
30
- slug: string;
31
- /** Full filesystem path to work item directory */
32
- path: string;
33
- }
34
- /**
35
- * Directory entry from filesystem traversal
36
- */
37
- interface DirectoryEntry {
38
- /** Directory name (basename) */
39
- name: string;
40
- /** Full absolute path */
41
- path: string;
42
- /** Whether this is a directory */
43
- isDirectory: boolean;
44
- }
45
- /**
46
- * Work item status
47
- */
48
- type WorkItemStatus = "OPEN" | "IN_PROGRESS" | "DONE";
49
- /**
50
- * Ordered list of work item statuses
51
- *
52
- * Used by both production code and tests to derive status values.
53
- * Per ADR-21: Never hardcode status names - derive from this constant.
54
- */
55
- declare const WORK_ITEM_STATUSES: readonly WorkItemStatus[];
56
-
57
- /**
58
- * Pattern matching for work item directory names
59
- */
60
-
61
- /**
62
- * Parse a work item directory name into structured data
63
- *
64
- * @param dirName - Directory name to parse
65
- * @returns Parsed work item with kind, number, and slug (path not included)
66
- * @throws Error if the directory name doesn't match the pattern or BSP number is invalid
67
- *
68
- * @example
69
- * ```typescript
70
- * parseWorkItemName("capability-21_core-cli")
71
- * // Returns: { kind: "capability", number: 20, slug: "core-cli" }
72
- *
73
- * parseWorkItemName("feature-21_pattern-matching")
74
- * // Returns: { kind: "feature", number: 21, slug: "pattern-matching" }
75
- * ```
76
- */
77
- declare function parseWorkItemName(dirName: string): Omit<WorkItem, "path">;
78
-
79
- /**
80
- * Validation functions for BSP (Behavior, Structure, Property) numbers
81
- */
82
- /**
83
- * BSP number range constants
84
- */
85
- declare const MIN_BSP_NUMBER = 10;
86
- declare const MAX_BSP_NUMBER = 99;
87
- /**
88
- * Check if a number is a valid BSP number
89
- *
90
- * @param n - Number to validate
91
- * @returns true if n is in range [10, 99], false otherwise
92
- *
93
- * @example
94
- * ```typescript
95
- * isValidBSPNumber(20) // true
96
- * isValidBSPNumber(9) // false
97
- * isValidBSPNumber(100) // false
98
- * ```
99
- */
100
- declare function isValidBSPNumber(n: number): boolean;
101
- /**
102
- * Validate a BSP number and throw if invalid
103
- *
104
- * @param n - Number to validate
105
- * @returns The validated number
106
- * @throws Error if the number is outside the valid range [10, 99]
107
- *
108
- * @example
109
- * ```typescript
110
- * validateBSPNumber(20) // returns 20
111
- * validateBSPNumber(5) // throws Error: "BSP number must be between 10 and 99, got 5"
112
- * ```
113
- */
114
- declare function validateBSPNumber(n: number): number;
115
-
116
- export { type DirectoryEntry, LEAF_KIND, MAX_BSP_NUMBER, MIN_BSP_NUMBER, WORK_ITEM_KINDS, WORK_ITEM_STATUSES, type WorkItem, type WorkItemKind, type WorkItemStatus, isValidBSPNumber, parseWorkItemName, validateBSPNumber };
package/dist/index.js DELETED
@@ -1,21 +0,0 @@
1
- import {
2
- LEAF_KIND,
3
- MAX_BSP_NUMBER,
4
- MIN_BSP_NUMBER,
5
- WORK_ITEM_KINDS,
6
- WORK_ITEM_STATUSES,
7
- isValidBSPNumber,
8
- parseWorkItemName,
9
- validateBSPNumber
10
- } from "./chunk-BQLLI7GS.js";
11
- export {
12
- LEAF_KIND,
13
- MAX_BSP_NUMBER,
14
- MIN_BSP_NUMBER,
15
- WORK_ITEM_KINDS,
16
- WORK_ITEM_STATUSES,
17
- isValidBSPNumber,
18
- parseWorkItemName,
19
- validateBSPNumber
20
- };
21
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}