@eskoubar95/spec 0.1.0 → 0.1.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.
Files changed (98) hide show
  1. package/dist/commands/help.d.ts +5 -0
  2. package/dist/commands/help.d.ts.map +1 -0
  3. package/dist/commands/help.js +23 -0
  4. package/dist/commands/help.js.map +1 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +30 -14
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/install.d.ts +5 -0
  9. package/dist/commands/install.d.ts.map +1 -0
  10. package/dist/commands/install.js +88 -0
  11. package/dist/commands/install.js.map +1 -0
  12. package/dist/commands/update.d.ts +5 -0
  13. package/dist/commands/update.d.ts.map +1 -0
  14. package/dist/commands/update.js +72 -0
  15. package/dist/commands/update.js.map +1 -0
  16. package/dist/commands/workspace.d.ts +5 -0
  17. package/dist/commands/workspace.d.ts.map +1 -0
  18. package/dist/commands/workspace.js +17 -0
  19. package/dist/commands/workspace.js.map +1 -0
  20. package/dist/index.js +42 -9
  21. package/dist/index.js.map +1 -1
  22. package/dist/lib/backup-cursor.d.ts +16 -0
  23. package/dist/lib/backup-cursor.d.ts.map +1 -0
  24. package/dist/lib/backup-cursor.js +50 -0
  25. package/dist/lib/backup-cursor.js.map +1 -0
  26. package/dist/lib/copy-template.d.ts +9 -1
  27. package/dist/lib/copy-template.d.ts.map +1 -1
  28. package/dist/lib/copy-template.js +94 -3
  29. package/dist/lib/copy-template.js.map +1 -1
  30. package/dist/lib/cursor-detection.d.ts +6 -0
  31. package/dist/lib/cursor-detection.d.ts.map +1 -0
  32. package/dist/lib/cursor-detection.js +31 -0
  33. package/dist/lib/cursor-detection.js.map +1 -0
  34. package/dist/lib/detection.d.ts +25 -0
  35. package/dist/lib/detection.d.ts.map +1 -0
  36. package/dist/lib/detection.js +186 -0
  37. package/dist/lib/detection.js.map +1 -0
  38. package/dist/lib/install-existing.d.ts +6 -0
  39. package/dist/lib/install-existing.d.ts.map +1 -0
  40. package/dist/lib/install-existing.js +63 -0
  41. package/dist/lib/install-existing.js.map +1 -0
  42. package/dist/lib/project-name.d.ts +7 -0
  43. package/dist/lib/project-name.d.ts.map +1 -0
  44. package/dist/lib/project-name.js +13 -0
  45. package/dist/lib/project-name.js.map +1 -0
  46. package/dist/lib/prompts.d.ts +6 -5
  47. package/dist/lib/prompts.d.ts.map +1 -1
  48. package/dist/lib/prompts.js +114 -0
  49. package/dist/lib/prompts.js.map +1 -1
  50. package/dist/lib/version-check.d.ts +21 -0
  51. package/dist/lib/version-check.d.ts.map +1 -0
  52. package/dist/lib/version-check.js +49 -0
  53. package/dist/lib/version-check.js.map +1 -0
  54. package/dist/lib/workspace.d.ts +7 -0
  55. package/dist/lib/workspace.d.ts.map +1 -0
  56. package/dist/lib/workspace.js +38 -0
  57. package/dist/lib/workspace.js.map +1 -0
  58. package/dist/types.d.ts +32 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +2 -2
  63. package/template/.cursor/commands/_shared/activation.md +220 -0
  64. package/template/.cursor/commands/_shared/coderabbit-integration.md +278 -0
  65. package/template/.cursor/commands/_shared/command-stacks.md +124 -0
  66. package/template/.cursor/commands/_shared/deployment-detection.md +294 -0
  67. package/template/.cursor/commands/_shared/detection.md +277 -0
  68. package/template/.cursor/commands/_shared/documentation-lookup.md +321 -0
  69. package/template/.cursor/commands/_shared/git-workflow.md +288 -0
  70. package/template/.cursor/commands/_shared/github-helpers.md +337 -0
  71. package/template/.cursor/commands/_shared/github-workflows.md +351 -0
  72. package/template/.cursor/commands/_shared/helper-metadata.md +481 -0
  73. package/template/.cursor/commands/_shared/linear-automation.md +388 -0
  74. package/template/.cursor/commands/_shared/linear-helpers.md +254 -0
  75. package/template/.cursor/commands/_shared/performance-monitoring.md +369 -0
  76. package/template/.cursor/commands/_shared/pr-description.md +279 -0
  77. package/template/.cursor/commands/_shared/retrospective-spec-creation.md +977 -0
  78. package/template/.cursor/commands/_shared/scaling.md +264 -0
  79. package/template/.cursor/commands/_shared/state-assertions.md +174 -0
  80. package/template/.cursor/commands/_shared/test-automation.md +388 -0
  81. package/template/.cursor/commands/_shared/verification-checkpoints.md +145 -0
  82. package/template/.cursor/commands/spec/audit.md +240 -0
  83. package/template/.cursor/commands/spec/evolve.md +163 -0
  84. package/template/.cursor/commands/spec/sync.md +196 -0
  85. package/template/.cursor/commands/tools/refactor.md +555 -0
  86. package/template/.cursor/rules/10-engineering.mdc +149 -0
  87. package/template/.cursor/rules/11-design.mdc +129 -0
  88. package/template/.cursor/rules/12-business.mdc +132 -0
  89. package/template/.cursor/rules/20-nextjs.mdc +146 -0
  90. package/template/.cursor/rules/21-api-design.mdc +176 -0
  91. package/template/.cursor/rules/30-database.mdc +183 -0
  92. package/template/.cursor/rules/31-testing.mdc +191 -0
  93. package/template/.cursor/scripts/validate-helpers.js +254 -0
  94. package/template/.sdd/detection-cache.json +1 -0
  95. package/template/.sdd/install-info.json +1 -0
  96. package/template/.sdd/version +1 -0
  97. package/template/spec/00-root-spec.md +8 -1
  98. package/template/work/backlog/tasks.local.md +92 -0
@@ -1,8 +1,31 @@
1
1
  import inquirer from 'inquirer';
2
+ import { normalizeProjectName } from './project-name.js';
3
+ import { isRunningInCursor } from './cursor-detection.js';
4
+ import { isExistingProject } from './detection.js';
2
5
  /**
3
6
  * Prompts the user for project initialization options
4
7
  */
5
8
  export async function promptInit() {
9
+ const cwd = process.cwd();
10
+ // Smart mode detection: Check if in Cursor + existing project
11
+ const inCursor = isRunningInCursor();
12
+ const isExisting = await isExistingProject(cwd);
13
+ if (inCursor && isExisting) {
14
+ // Auto-suggest install mode
15
+ const { shouldInstall } = await inquirer.prompt([
16
+ {
17
+ type: 'confirm',
18
+ name: 'shouldInstall',
19
+ message: 'Detected you\'re in an existing project in Cursor. Install SDD to this project?',
20
+ default: true,
21
+ },
22
+ ]);
23
+ if (shouldInstall) {
24
+ // This will be handled by the init command
25
+ throw new Error('SWITCH_TO_INSTALL');
26
+ }
27
+ }
28
+ // Normal init flow
6
29
  const answers = await inquirer.prompt([
7
30
  {
8
31
  type: 'input',
@@ -18,6 +41,14 @@ export async function promptInit() {
18
41
  }
19
42
  return true;
20
43
  },
44
+ filter: (input) => {
45
+ // Normalize project name: convert spaces to hyphens, lowercase
46
+ return normalizeProjectName(input);
47
+ },
48
+ transformer: (input) => {
49
+ // Show normalized version while typing
50
+ return normalizeProjectName(input);
51
+ },
21
52
  },
22
53
  {
23
54
  type: 'list',
@@ -35,7 +66,90 @@ export async function promptInit() {
35
66
  message: 'Initialize git repository?',
36
67
  default: true,
37
68
  },
69
+ ...(isRunningInCursor() ? [] : [
70
+ {
71
+ type: 'confirm',
72
+ name: 'openInCursor',
73
+ message: 'Open in Cursor?',
74
+ default: true,
75
+ },
76
+ ]),
38
77
  ]);
39
78
  return answers;
40
79
  }
80
+ /**
81
+ * Prompts the user for installation options
82
+ */
83
+ export async function promptInstall(projectPath) {
84
+ const inCursor = isRunningInCursor();
85
+ const isExisting = await isExistingProject(projectPath);
86
+ // Auto-detect project path if in Cursor and current directory is a project
87
+ let finalProjectPath = projectPath;
88
+ if (inCursor && isExisting && projectPath === process.cwd()) {
89
+ // Use current directory automatically
90
+ }
91
+ else {
92
+ const { path: selectedPath } = await inquirer.prompt([
93
+ {
94
+ type: 'input',
95
+ name: 'path',
96
+ message: 'Project path:',
97
+ default: projectPath,
98
+ validate: (input) => {
99
+ if (!input.trim()) {
100
+ return 'Project path cannot be empty';
101
+ }
102
+ return true;
103
+ },
104
+ },
105
+ ]);
106
+ finalProjectPath = selectedPath;
107
+ }
108
+ // Check if .cursor folder exists
109
+ const { hasCursorFolder } = await import('./backup-cursor.js').then(m => m.checkCursorFolder(finalProjectPath));
110
+ const answers = await inquirer.prompt([
111
+ {
112
+ type: 'list',
113
+ name: 'backupStrategy',
114
+ message: hasCursorFolder ? 'Backup existing .cursor folder or merge?' : 'Backup strategy:',
115
+ choices: [
116
+ { name: 'Backup existing .cursor folder', value: 'backup' },
117
+ { name: 'Merge with existing', value: 'merge' },
118
+ ],
119
+ default: 'backup',
120
+ when: hasCursorFolder,
121
+ },
122
+ {
123
+ type: 'confirm',
124
+ name: 'installSpecFolders',
125
+ message: 'Install spec/ and work/ folders?',
126
+ default: true,
127
+ },
128
+ {
129
+ type: 'confirm',
130
+ name: 'createRootSpec',
131
+ message: 'Create spec/00-root-spec.md if missing?',
132
+ default: true,
133
+ },
134
+ {
135
+ type: 'confirm',
136
+ name: 'initializeDetection',
137
+ message: 'Initialize detection cache?',
138
+ default: true,
139
+ },
140
+ ...(isRunningInCursor() ? [] : [
141
+ {
142
+ type: 'confirm',
143
+ name: 'openInCursor',
144
+ message: 'Open in Cursor?',
145
+ default: true,
146
+ },
147
+ ]),
148
+ ]);
149
+ return {
150
+ ...answers,
151
+ projectPath: finalProjectPath,
152
+ backupStrategy: answers.backupStrategy || 'backup', // Default if not asked
153
+ };
154
+ }
41
155
  //# sourceMappingURL=prompts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/lib/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAQhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAc;QACjD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,6BAA6B;YACtC,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE;gBAC1B,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;oBAClB,OAAO,8BAA8B,CAAC;gBACxC,CAAC;gBACD,oCAAoC;gBACpC,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/B,OAAO,0CAA0C,CAAC;gBACpD,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,YAAY;YACrB,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;gBACjC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;aACpC;YACD,OAAO,EAAE,OAAO;SACjB;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,4BAA4B;YACrC,OAAO,EAAE,IAAI;SACd;KACF,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/lib/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface VersionInfo {
2
+ currentVersion?: string;
3
+ latestVersion: string;
4
+ needsUpdate: boolean;
5
+ }
6
+ /**
7
+ * Gets the current package version from package.json
8
+ */
9
+ export declare function getPackageVersion(): Promise<string>;
10
+ /**
11
+ * Checks the current version and determines if an update is needed
12
+ * @param projectPath - Path to the project
13
+ */
14
+ export declare function checkVersion(projectPath: string): Promise<VersionInfo>;
15
+ /**
16
+ * Updates the version file in the project
17
+ * @param projectPath - Path to the project
18
+ * @param version - Version string to write
19
+ */
20
+ export declare function updateVersionFile(projectPath: string, version: string): Promise<void>;
21
+ //# sourceMappingURL=version-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-check.d.ts","sourceRoot":"","sources":["../../src/lib/version-check.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CASzD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB5E;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3F"}
@@ -0,0 +1,49 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ /**
4
+ * Gets the current package version from package.json
5
+ */
6
+ export async function getPackageVersion() {
7
+ const packageJsonPath = path.resolve(import.meta.url.replace('file://', ''), '../../../package.json');
8
+ try {
9
+ const packageJson = await fs.readJson(packageJsonPath);
10
+ return packageJson.version || '0.1.0';
11
+ }
12
+ catch {
13
+ return '0.1.0'; // Fallback
14
+ }
15
+ }
16
+ /**
17
+ * Checks the current version and determines if an update is needed
18
+ * @param projectPath - Path to the project
19
+ */
20
+ export async function checkVersion(projectPath) {
21
+ const versionPath = path.join(projectPath, '.sdd', 'version');
22
+ const latestVersion = await getPackageVersion();
23
+ let currentVersion;
24
+ if (await fs.pathExists(versionPath)) {
25
+ try {
26
+ currentVersion = (await fs.readFile(versionPath, 'utf-8')).trim();
27
+ }
28
+ catch {
29
+ // Ignore read errors
30
+ }
31
+ }
32
+ const needsUpdate = currentVersion !== undefined && currentVersion !== latestVersion;
33
+ return {
34
+ currentVersion,
35
+ latestVersion,
36
+ needsUpdate,
37
+ };
38
+ }
39
+ /**
40
+ * Updates the version file in the project
41
+ * @param projectPath - Path to the project
42
+ * @param version - Version string to write
43
+ */
44
+ export async function updateVersionFile(projectPath, version) {
45
+ const versionPath = path.join(projectPath, '.sdd', 'version');
46
+ await fs.ensureDir(path.dirname(versionPath));
47
+ await fs.writeFile(versionPath, version, 'utf-8');
48
+ }
49
+ //# sourceMappingURL=version-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../src/lib/version-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAEtG,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACvD,OAAO,WAAW,CAAC,OAAO,IAAI,OAAO,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC,CAAC,WAAW;IAC7B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,aAAa,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAEhD,IAAI,cAAkC,CAAC;IACvC,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,cAAc,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,CAAC;QAAC,MAAM,CAAC;YACP,qBAAqB;QACvB,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,aAAa,CAAC;IAErF,OAAO;QACL,cAAc;QACd,aAAa;QACb,WAAW;KACZ,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAAmB,EAAE,OAAe;IAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Opens a project in Cursor IDE
3
+ * @param projectPath - Path to the project to open
4
+ * @param skipIfAlreadyInCursor - Skip if already running in Cursor (default: true)
5
+ */
6
+ export declare function openInCursor(projectPath: string, skipIfAlreadyInCursor?: boolean): Promise<void>;
7
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/lib/workspace.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,qBAAqB,GAAE,OAAc,GACpC,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
@@ -0,0 +1,38 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import { isRunningInCursor } from './cursor-detection.js';
4
+ const execAsync = promisify(exec);
5
+ /**
6
+ * Opens a project in Cursor IDE
7
+ * @param projectPath - Path to the project to open
8
+ * @param skipIfAlreadyInCursor - Skip if already running in Cursor (default: true)
9
+ */
10
+ export async function openInCursor(projectPath, skipIfAlreadyInCursor = true) {
11
+ // Check if already in Cursor
12
+ if (skipIfAlreadyInCursor && isRunningInCursor()) {
13
+ console.log('\n✓ You are already in Cursor. No need to open the project.\n');
14
+ return;
15
+ }
16
+ // Check if cursor command is available
17
+ try {
18
+ await execAsync('which cursor');
19
+ }
20
+ catch {
21
+ console.log('\n⚠️ Cursor command not found in PATH.');
22
+ console.log(' Please open the project manually in Cursor IDE.');
23
+ console.log(` Path: ${projectPath}\n`);
24
+ return;
25
+ }
26
+ // Open project in Cursor
27
+ try {
28
+ await execAsync(`cursor "${projectPath}"`);
29
+ console.log(`\n✓ Opening project in Cursor...\n`);
30
+ }
31
+ catch (error) {
32
+ console.error('\n❌ Error opening project in Cursor:');
33
+ console.error(` ${error instanceof Error ? error.message : String(error)}`);
34
+ console.log(`\n Please open the project manually in Cursor IDE.`);
35
+ console.log(` Path: ${projectPath}\n`);
36
+ }
37
+ }
38
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/lib/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,WAAmB,EACnB,wBAAiC,IAAI;IAErC,6BAA6B;IAC7B,IAAI,qBAAqB,IAAI,iBAAiB,EAAE,EAAE,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC7E,OAAO;IACT,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,IAAI,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,WAAW,WAAW,GAAG,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,IAAI,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
@@ -0,0 +1,32 @@
1
+ export interface InitAnswers {
2
+ projectName: string;
3
+ taskMode: 'local' | 'linear';
4
+ gitInit: boolean;
5
+ openInCursor?: boolean;
6
+ }
7
+ export interface InstallAnswers {
8
+ projectPath: string;
9
+ backupStrategy: 'backup' | 'merge';
10
+ installSpecFolders: boolean;
11
+ createRootSpec: boolean;
12
+ initializeDetection: boolean;
13
+ openInCursor?: boolean;
14
+ }
15
+ export interface ProjectInfo {
16
+ hasCursorFolder: boolean;
17
+ hasCodebase: boolean;
18
+ projectType?: string;
19
+ techStack?: string[];
20
+ }
21
+ export interface DetectionResults {
22
+ projectType: string;
23
+ projectSize: 'small' | 'medium' | 'large' | 'enterprise';
24
+ technologies: string[];
25
+ phase?: 'initialization' | 'expansion' | 'maintenance' | 'migration' | 'legacy';
26
+ }
27
+ export interface VersionInfo {
28
+ currentVersion?: string;
29
+ latestVersion: string;
30
+ needsUpdate: boolean;
31
+ }
32
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC;IACnC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;IACzD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;CACjF;AAED,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eskoubar95/spec",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "spec": "dist/index.js"
@@ -27,4 +27,4 @@
27
27
  "@types/node": "^20.11.0",
28
28
  "typescript": "^5.3.3"
29
29
  }
30
- }
30
+ }
@@ -0,0 +1,220 @@
1
+ ---
2
+ helper_id: activation
3
+ load_when:
4
+ - always
5
+ sections:
6
+ matching:
7
+ title: "Match detection results"
8
+ lines: [1, 50]
9
+ dependencies:
10
+ title: "Check rule dependencies"
11
+ lines: [51, 100]
12
+ activation:
13
+ title: "Activate matching rules"
14
+ lines: [101, 150]
15
+ always_load: true
16
+ ---
17
+
18
+ # Rule Activation Engine
19
+
20
+ This engine activates relevant rules based on project detection results.
21
+
22
+ ## Purpose
23
+
24
+ After project detection, this engine:
25
+ - Matches detection results against rule metadata
26
+ - Activates relevant rules based on activation conditions
27
+ - Handles rule dependencies (requires field)
28
+ - Outputs active rule list with categories
29
+
30
+ ## Activation Algorithm
31
+
32
+ **Step 1: Always activate foundation rules**
33
+ - `00-pos.mdc` - Project Operating System (always apply)
34
+ - `01-sdd.mdc` - Spec-Driven Development (always apply)
35
+ - `02-work-mode.mdc` - Work Mode (always apply)
36
+
37
+ **Step 2: Match detection results against rule metadata**
38
+
39
+ **2.1: Check for tech stack in spec (if available)**
40
+ - Read tech stack from `spec/08-infrastructure.md` or `spec/02-architecture.md`
41
+ - If tech stack found → use it as primary source for framework/tool detection
42
+ - For each framework/tool in tech stack:
43
+ - Check if rule exists (e.g., `20-nextjs.mdc` for "Next.js")
44
+ - If rule exists → add to activation queue
45
+ - If rule doesn't exist → note for user guidance: "Framework [X] detected but no specific rule exists. Should I create a framework-specific rule, or use general patterns with Context7 documentation lookup?"
46
+
47
+ **2.2: Match detection results against rule metadata**
48
+
49
+ **Rule Metadata Cache Strategy:**
50
+
51
+ 1. **Check cache validity:**
52
+ - Check if `.sdd/rule-metadata-cache.json` exists
53
+ - Check if cache is valid (compare rule file modification times with cache timestamp)
54
+ - If cache valid → use cached metadata
55
+ - If cache invalid or missing → rebuild cache
56
+
57
+ 2. **Rebuild cache (if needed):**
58
+ - Scan all rule files in `.cursor/rules/`
59
+ - Extract metadata (activation conditions, requires, etc.)
60
+ - Store in `.sdd/rule-metadata-cache.json`:
61
+ ```json
62
+ {
63
+ "rules": {
64
+ "20-nextjs.mdc": {
65
+ "activation": {
66
+ "projectTypes": ["web-app"],
67
+ "technologies": ["nextjs"]
68
+ },
69
+ "requires": ["10-engineering"]
70
+ }
71
+ },
72
+ "last_updated": "2026-01-07T12:00:00Z",
73
+ "rule_files": {
74
+ "20-nextjs.mdc": {
75
+ "mtime": 1704633600000
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ 3. **Match detection results against cached metadata:**
82
+ - For each rule in cache:
83
+ - Check if rule matches detection:
84
+ - `projectTypes` contains detected project type
85
+ - `projectSizes` contains detected project size
86
+ - `projectPhases` contains detected project phase
87
+ - `technologies` contains any detected technology (from package.json or spec tech stack)
88
+ - If match → add to activation queue
89
+
90
+ **Cache Invalidation:**
91
+ - Invalidate cache if any rule file is modified (compare mtime)
92
+ - Invalidate cache if new rule files are added
93
+ - Invalidate cache if rule files are deleted
94
+ - Rebuild cache automatically when invalid
95
+
96
+ **Step 3: Check rule dependencies**
97
+
98
+ For each rule in activation queue:
99
+ 1. Check `requires` field
100
+ 2. If required rules not active → activate them first
101
+ 3. Handle circular dependencies (warn and break cycle)
102
+
103
+ **Step 4: Activate matching rules**
104
+
105
+ Activate rules in dependency order:
106
+ 1. Foundation rules (already active)
107
+ 2. Domain rules (10-engineering, 11-design, 12-business)
108
+ 3. Technology rules (20-nextjs, 21-api-design, 30-database, etc.)
109
+
110
+ **Step 5: Output active rule list**
111
+
112
+ ```markdown
113
+ **Active Rule Sets:**
114
+
115
+ **Foundation (always active):**
116
+ - 00-pos.mdc - Project Operating System
117
+ - 01-sdd.mdc - Spec-Driven Development
118
+ - 02-work-mode.mdc - Work Mode
119
+
120
+ **Domain (context-based):**
121
+ - 10-engineering.mdc - Engineering patterns
122
+ - 11-design.mdc - Design patterns
123
+
124
+ **Technology (auto-activated):**
125
+ - 20-nextjs.mdc - Next.js patterns
126
+ - 21-api-design.mdc - API design patterns
127
+ - 30-database.mdc - Database patterns
128
+ ```
129
+
130
+ ## Rule Metadata Format
131
+
132
+ Each rule file should include activation metadata:
133
+
134
+ ```markdown
135
+ ---
136
+ title: [Rule Title]
137
+ description: [Description]
138
+ owner: sdd-system
139
+ severity: warn
140
+ globs: [File patterns - optional]
141
+ alwaysApply: false
142
+ activation:
143
+ projectTypes: [web-app, cli-tool, library, api-service, mobile-app, monorepo]
144
+ projectSizes: [small, medium, large, enterprise]
145
+ projectPhases: [initialization, expansion, maintenance, migration, legacy]
146
+ technologies: [nextjs, react, postgres, clerk, tailwindcss, jest]
147
+ requires: [10-engineering, 11-design]
148
+ ---
149
+ ```
150
+
151
+ ## Activation Logic Examples
152
+
153
+ **Example 1: Next.js web app (medium, expansion)**
154
+ - Foundation: 00-pos, 01-sdd, 02-work-mode
155
+ - Domain: 10-engineering, 11-design
156
+ - Technology: 20-nextjs, 21-api-design (if API routes exist), 30-database (if database detected)
157
+
158
+ **Example 2: CLI tool (small, initialization)**
159
+ - Foundation: 00-pos, 01-sdd, 02-work-mode
160
+ - Domain: 10-engineering
161
+ - Technology: 40-cli-patterns (if exists)
162
+
163
+ **Example 3: Legacy Express API (large, maintenance)**
164
+ - Foundation: 00-pos, 01-sdd, 02-work-mode
165
+ - Domain: 10-engineering
166
+ - Technology: 21-api-design, 30-database
167
+
168
+ ## User Override
169
+
170
+ Users can override activation:
171
+ - Manually activate/deactivate specific rules
172
+ - Force activation of rules that didn't match
173
+ - Disable auto-activation for specific rules
174
+
175
+ ## Rule Metadata Cache
176
+
177
+ **Cache Location:** `.sdd/rule-metadata-cache.json`
178
+
179
+ **Cache Structure:**
180
+ ```json
181
+ {
182
+ "rules": {
183
+ "20-nextjs.mdc": {
184
+ "activation": {
185
+ "projectTypes": ["web-app"],
186
+ "projectSizes": ["small", "medium", "large"],
187
+ "projectPhases": ["initialization", "expansion"],
188
+ "technologies": ["nextjs", "react"]
189
+ },
190
+ "requires": ["10-engineering"]
191
+ }
192
+ },
193
+ "last_updated": "2026-01-07T12:00:00Z",
194
+ "rule_files": {
195
+ "20-nextjs.mdc": {
196
+ "mtime": 1704633600000
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ **Cache Management:**
203
+ - **Build cache:** Parse all rule files, extract metadata, store in cache
204
+ - **Validate cache:** Compare rule file mtimes with cache mtimes
205
+ - **Invalidate cache:** If any rule file modified, rebuild cache
206
+ - **Use cache:** Read from cache instead of scanning all rule files
207
+
208
+ **Benefits:**
209
+ - Faster activation (read from cache instead of scanning all files)
210
+ - Reduced token consumption (cache is small JSON file)
211
+ - Automatic invalidation ensures cache stays current
212
+
213
+ ## Usage in Commands
214
+
215
+ All SDD commands should:
216
+ 1. Run detection (or read from cache)
217
+ 2. Run activation engine (use rule metadata cache)
218
+ 3. Include active rule list in state assertion
219
+ 4. Apply active rules during execution
220
+