@nlaprell/shipit 1.0.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.
Files changed (160) hide show
  1. package/.cursor/commands/create_intent_from_issue.md +28 -0
  2. package/.cursor/commands/create_pr.md +28 -0
  3. package/.cursor/commands/dashboard.md +39 -0
  4. package/.cursor/commands/deploy.md +152 -0
  5. package/.cursor/commands/drift_check.md +36 -0
  6. package/.cursor/commands/fix.md +39 -0
  7. package/.cursor/commands/generate_release_plan.md +31 -0
  8. package/.cursor/commands/generate_roadmap.md +38 -0
  9. package/.cursor/commands/help.md +37 -0
  10. package/.cursor/commands/init_project.md +26 -0
  11. package/.cursor/commands/kill.md +72 -0
  12. package/.cursor/commands/new_intent.md +68 -0
  13. package/.cursor/commands/pr.md +77 -0
  14. package/.cursor/commands/revert-plan.md +58 -0
  15. package/.cursor/commands/risk.md +64 -0
  16. package/.cursor/commands/rollback.md +43 -0
  17. package/.cursor/commands/scope_project.md +53 -0
  18. package/.cursor/commands/ship.md +345 -0
  19. package/.cursor/commands/status.md +71 -0
  20. package/.cursor/commands/suggest.md +44 -0
  21. package/.cursor/commands/test_shipit.md +197 -0
  22. package/.cursor/commands/verify.md +50 -0
  23. package/.cursor/rules/architect.mdc +84 -0
  24. package/.cursor/rules/assumption-extractor.mdc +95 -0
  25. package/.cursor/rules/docs.mdc +66 -0
  26. package/.cursor/rules/implementer.mdc +112 -0
  27. package/.cursor/rules/pm.mdc +136 -0
  28. package/.cursor/rules/qa.mdc +97 -0
  29. package/.cursor/rules/security.mdc +90 -0
  30. package/.cursor/rules/steward.mdc +99 -0
  31. package/.cursor/rules/test-runner.mdc +196 -0
  32. package/AGENTS.md +121 -0
  33. package/README.md +264 -0
  34. package/_system/architecture/CANON.md +159 -0
  35. package/_system/architecture/invariants.yml +87 -0
  36. package/_system/architecture/project-schema.json +98 -0
  37. package/_system/architecture/workflow-state-layout.md +68 -0
  38. package/_system/artifacts/SYSTEM_STATE.md +43 -0
  39. package/_system/artifacts/confidence-calibration.json +16 -0
  40. package/_system/artifacts/dependencies.md +46 -0
  41. package/_system/artifacts/framework-files-manifest.json +179 -0
  42. package/_system/artifacts/usage.json +1 -0
  43. package/_system/behaviors/DO_RELEASE.md +371 -0
  44. package/_system/behaviors/DO_RELEASE_AI.md +329 -0
  45. package/_system/behaviors/PREPARE_RELEASE.md +373 -0
  46. package/_system/behaviors/PREPARE_RELEASE_AI.md +234 -0
  47. package/_system/behaviors/WORK_ROOT_PLATFORM_ISSUES.md +140 -0
  48. package/_system/behaviors/WORK_TEST_PLAN_ISSUES.md +380 -0
  49. package/_system/do-not-repeat/abandoned-designs.md +18 -0
  50. package/_system/do-not-repeat/bad-patterns.md +19 -0
  51. package/_system/do-not-repeat/failed-experiments.md +18 -0
  52. package/_system/do-not-repeat/rejected-libraries.md +19 -0
  53. package/_system/drift/baselines.md +49 -0
  54. package/_system/drift/metrics.md +33 -0
  55. package/_system/golden-data/.gitkeep +0 -0
  56. package/_system/golden-data/README.md +47 -0
  57. package/_system/reports/mutation/mutation.html +492 -0
  58. package/_system/security/audit-allowlist.json +4 -0
  59. package/bin/create-shipit-app +29 -0
  60. package/bin/shipit +183 -0
  61. package/cli/src/commands/check.js +82 -0
  62. package/cli/src/commands/create.js +195 -0
  63. package/cli/src/commands/init.js +267 -0
  64. package/cli/src/commands/upgrade.js +196 -0
  65. package/cli/src/utils/config.js +27 -0
  66. package/cli/src/utils/file-copy.js +144 -0
  67. package/cli/src/utils/gitignore-merge.js +44 -0
  68. package/cli/src/utils/manifest.js +105 -0
  69. package/cli/src/utils/package-json-merge.js +163 -0
  70. package/cli/src/utils/project-json-merge.js +57 -0
  71. package/cli/src/utils/prompts.js +30 -0
  72. package/cli/src/utils/stack-detection.js +56 -0
  73. package/cli/src/utils/stack-files.js +364 -0
  74. package/cli/src/utils/upgrade-backup.js +159 -0
  75. package/cli/src/utils/version.js +64 -0
  76. package/dashboard-app/README.md +73 -0
  77. package/dashboard-app/eslint.config.js +23 -0
  78. package/dashboard-app/index.html +13 -0
  79. package/dashboard-app/package.json +30 -0
  80. package/dashboard-app/pnpm-lock.yaml +2721 -0
  81. package/dashboard-app/public/dashboard.json +66 -0
  82. package/dashboard-app/public/vite.svg +1 -0
  83. package/dashboard-app/src/App.css +141 -0
  84. package/dashboard-app/src/App.tsx +155 -0
  85. package/dashboard-app/src/assets/react.svg +1 -0
  86. package/dashboard-app/src/index.css +68 -0
  87. package/dashboard-app/src/main.tsx +10 -0
  88. package/dashboard-app/tsconfig.app.json +28 -0
  89. package/dashboard-app/tsconfig.json +4 -0
  90. package/dashboard-app/tsconfig.node.json +26 -0
  91. package/dashboard-app/vite.config.ts +7 -0
  92. package/package.json +116 -0
  93. package/scripts/README.md +70 -0
  94. package/scripts/audit-check.sh +125 -0
  95. package/scripts/calibration-report.sh +198 -0
  96. package/scripts/check-readiness.sh +155 -0
  97. package/scripts/collect-metrics.sh +116 -0
  98. package/scripts/command-manifest.yml +131 -0
  99. package/scripts/create-test-plan-issue.sh +110 -0
  100. package/scripts/dashboard-start.sh +16 -0
  101. package/scripts/deploy.sh +170 -0
  102. package/scripts/drift-check.sh +93 -0
  103. package/scripts/execute-rollback.sh +177 -0
  104. package/scripts/export-dashboard-json.js +208 -0
  105. package/scripts/fix-intents.sh +239 -0
  106. package/scripts/generate-dashboard.sh +136 -0
  107. package/scripts/generate-docs.sh +279 -0
  108. package/scripts/generate-project-context.sh +142 -0
  109. package/scripts/generate-release-plan.sh +443 -0
  110. package/scripts/generate-roadmap.sh +189 -0
  111. package/scripts/generate-system-state.sh +95 -0
  112. package/scripts/gh/create-intent-from-issue.sh +82 -0
  113. package/scripts/gh/create-issue-from-intent.sh +59 -0
  114. package/scripts/gh/create-pr.sh +41 -0
  115. package/scripts/gh/link-issue.sh +44 -0
  116. package/scripts/gh/on-ship-update-issue.sh +42 -0
  117. package/scripts/headless/README.md +8 -0
  118. package/scripts/headless/call-llm.js +109 -0
  119. package/scripts/headless/run-phase.sh +99 -0
  120. package/scripts/help.sh +271 -0
  121. package/scripts/init-project.sh +976 -0
  122. package/scripts/kill-intent.sh +125 -0
  123. package/scripts/lib/common.sh +29 -0
  124. package/scripts/lib/intent.sh +61 -0
  125. package/scripts/lib/progress.sh +57 -0
  126. package/scripts/lib/suggest-next.sh +131 -0
  127. package/scripts/lib/validate-intents.sh +240 -0
  128. package/scripts/lib/verify-outputs.sh +55 -0
  129. package/scripts/lib/workflow_state.sh +201 -0
  130. package/scripts/new-intent.sh +271 -0
  131. package/scripts/publish-npm.sh +28 -0
  132. package/scripts/scope-project.sh +380 -0
  133. package/scripts/setup-worktrees.sh +125 -0
  134. package/scripts/status.sh +278 -0
  135. package/scripts/suggest.sh +173 -0
  136. package/scripts/test-headless.sh +47 -0
  137. package/scripts/test-shipit.sh +52 -0
  138. package/scripts/test-workflow-state.sh +49 -0
  139. package/scripts/usage-report.sh +47 -0
  140. package/scripts/usage.sh +58 -0
  141. package/scripts/validate-cursor.sh +151 -0
  142. package/scripts/validate-project.sh +71 -0
  143. package/scripts/validate-vscode.sh +146 -0
  144. package/scripts/verify.sh +153 -0
  145. package/scripts/workflow-orchestrator.sh +97 -0
  146. package/scripts/workflow-templates/01_analysis.md.tpl +25 -0
  147. package/scripts/workflow-templates/02_plan.md.tpl +30 -0
  148. package/scripts/workflow-templates/03_implementation.md.tpl +25 -0
  149. package/scripts/workflow-templates/04_verification.md.tpl +29 -0
  150. package/scripts/workflow-templates/05_release_notes.md.tpl +16 -0
  151. package/scripts/workflow-templates/05_verification_legacy.md.tpl +6 -0
  152. package/scripts/workflow-templates/active.md.tpl +18 -0
  153. package/scripts/workflow-templates/phases.yml +39 -0
  154. package/stryker.conf.json +8 -0
  155. package/work/intent/templates/api-endpoint.md +124 -0
  156. package/work/intent/templates/bugfix.md +116 -0
  157. package/work/intent/templates/frontend-feature.md +115 -0
  158. package/work/intent/templates/generic.md +122 -0
  159. package/work/intent/templates/infra-change.md +121 -0
  160. package/work/intent/templates/refactor.md +116 -0
@@ -0,0 +1,4 @@
1
+ {
2
+ "version": 1,
3
+ "advisories": []
4
+ }
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * create-shipit-app - Create a new ShipIt project
5
+ *
6
+ * This is an alias for `shipit create <project-name>`
7
+ */
8
+
9
+ import { fileURLToPath } from 'url';
10
+ import { dirname, join } from 'path';
11
+ import { spawn } from 'child_process';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ // Get shipit CLI path
17
+ const shipitPath = join(__dirname, 'shipit');
18
+
19
+ // Forward all arguments to shipit create
20
+ const args = ['create', ...process.argv.slice(2)];
21
+
22
+ const child = spawn('node', [shipitPath, ...args], {
23
+ stdio: 'inherit',
24
+ cwd: process.cwd()
25
+ });
26
+
27
+ child.on('exit', (code) => {
28
+ process.exit(code || 0);
29
+ });
package/bin/shipit ADDED
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ShipIt CLI - Main entry point
5
+ *
6
+ * Commands:
7
+ * shipit init - Attach ShipIt to existing project
8
+ * shipit upgrade - Upgrade ShipIt framework files
9
+ * shipit check - Validate ShipIt installation
10
+ * shipit create <name> - Create new ShipIt project (alias for create-shipit-app)
11
+ */
12
+
13
+ import { program } from 'commander';
14
+ import { fileURLToPath } from 'url';
15
+ import { dirname, join } from 'path';
16
+ import { existsSync, readFileSync } from 'fs';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+
21
+ // Import CLI modules - use dynamic imports to handle ESM
22
+ let initCommand, upgradeCommand, checkCommand, createCommand, listBackupsCommand, restoreCommand;
23
+
24
+ async function loadCommands() {
25
+ const init = await import('../cli/src/commands/init.js');
26
+ const upgrade = await import('../cli/src/commands/upgrade.js');
27
+ const check = await import('../cli/src/commands/check.js');
28
+ const create = await import('../cli/src/commands/create.js');
29
+
30
+ initCommand = init.initCommand;
31
+ upgradeCommand = upgrade.upgradeCommand;
32
+ checkCommand = check.checkCommand;
33
+ createCommand = create.createCommand;
34
+ listBackupsCommand = upgrade.listBackupsCommand;
35
+ restoreCommand = upgrade.restoreCommand;
36
+ }
37
+
38
+ // Get version from package.json
39
+ const packageJsonPath = join(__dirname, '..', 'package.json');
40
+ let version = '0.6.0';
41
+ try {
42
+ const pkgContent = readFileSync(packageJsonPath, 'utf-8');
43
+ const pkg = JSON.parse(pkgContent);
44
+ version = pkg.version || version;
45
+ } catch (e) {
46
+ // Fallback to default version
47
+ }
48
+
49
+ // Load commands
50
+ await loadCommands();
51
+
52
+ program
53
+ .name('shipit')
54
+ .description('ShipIt - AI-native Software Development Life Cycle framework')
55
+ .version(version);
56
+
57
+ // Init command
58
+ program
59
+ .command('init')
60
+ .description('Attach ShipIt to an existing project')
61
+ .option('--path <dir>', 'Target directory (default: current directory)')
62
+ .option('--tech-stack <stack>', 'Tech stack (typescript-nodejs | python | other)')
63
+ .option('--description <text>', 'Project description')
64
+ .option('--high-risk <domains>', 'Comma-separated high-risk domains')
65
+ .option('--non-interactive', 'Use defaults/CLI args only, no prompts')
66
+ .option('--force', 'Overwrite existing ShipIt files')
67
+ .action(async (options) => {
68
+ try {
69
+ await initCommand(options);
70
+ } catch (error) {
71
+ console.error(`ERROR: ${error.message}`);
72
+ if (error.suggestedFix) {
73
+ console.error(` ${error.suggestedFix}`);
74
+ }
75
+ process.exit(error.exitCode || 2);
76
+ }
77
+ });
78
+
79
+ // Upgrade command
80
+ program
81
+ .command('upgrade')
82
+ .description('Upgrade ShipIt framework files to latest version')
83
+ .option('--path <dir>', 'Target directory (default: current directory)')
84
+ .option('--backup-dir <dir>', 'Backup directory (default: ._shipit_backup/)')
85
+ .option('--dry-run', 'Show what would be changed without making changes')
86
+ .option('--force', 'Skip prompts, overwrite all framework files')
87
+ .action(async (options) => {
88
+ try {
89
+ await upgradeCommand(options);
90
+ } catch (error) {
91
+ console.error(`ERROR: ${error.message}`);
92
+ if (error.suggestedFix) {
93
+ console.error(` ${error.suggestedFix}`);
94
+ }
95
+ process.exit(error.exitCode || 2);
96
+ }
97
+ });
98
+
99
+ // List backups
100
+ program
101
+ .command('list-backups')
102
+ .description('List ShipIt backup files from last upgrade')
103
+ .option('--path <dir>', 'Target directory (default: current directory)')
104
+ .option('--backup-dir <dir>', 'Backup directory (default: ._shipit_backup/)')
105
+ .action(async (options) => {
106
+ try {
107
+ await listBackupsCommand(options);
108
+ } catch (error) {
109
+ console.error(`ERROR: ${error.message}`);
110
+ process.exit(error.exitCode || 2);
111
+ }
112
+ });
113
+
114
+ // Restore from backup
115
+ program
116
+ .command('restore <backup-path>')
117
+ .description('Restore a file from backup (path relative to project or ._shipit_backup/)')
118
+ .option('--path <dir>', 'Target directory (default: current directory)')
119
+ .option('--backup-dir <dir>', 'Backup directory (default: ._shipit_backup/)')
120
+ .option('--remove-backup', 'Remove backup file after restore')
121
+ .action(async (backupPath, options) => {
122
+ try {
123
+ await restoreCommand(backupPath, options);
124
+ } catch (error) {
125
+ console.error(`ERROR: ${error.message}`);
126
+ process.exit(error.exitCode || 2);
127
+ }
128
+ });
129
+
130
+ // Check command
131
+ program
132
+ .command('check')
133
+ .description('Validate ShipIt installation and show project status')
134
+ .option('--path <dir>', 'Target directory (default: current directory)')
135
+ .option('--json', 'Output JSON instead of human-readable')
136
+ .action(async (options) => {
137
+ try {
138
+ await checkCommand(options);
139
+ } catch (error) {
140
+ console.error(`ERROR: ${error.message}`);
141
+ if (error.suggestedFix) {
142
+ console.error(` ${error.suggestedFix}`);
143
+ }
144
+ process.exit(error.exitCode || 2);
145
+ }
146
+ });
147
+
148
+ // Create command
149
+ program
150
+ .command('create <project-name>')
151
+ .description('Create a new ShipIt project')
152
+ .option('--tech-stack <stack>', 'Tech stack (typescript-nodejs | python | other)')
153
+ .option('--description <text>', 'Project description')
154
+ .option('--high-risk <domains>', 'Comma-separated high-risk domains')
155
+ .option('--non-interactive', 'Use defaults/CLI args only, no prompts')
156
+ .option('--skip-git', 'Don\'t initialize git repo')
157
+ .option('--skip-install', 'Don\'t run package manager install')
158
+ .action(async (projectName, options) => {
159
+ try {
160
+ await createCommand(projectName, options);
161
+ } catch (error) {
162
+ console.error(`ERROR: ${error.message}`);
163
+ if (error.suggestedFix) {
164
+ console.error(` ${error.suggestedFix}`);
165
+ }
166
+ process.exit(error.exitCode || 2);
167
+ }
168
+ });
169
+
170
+ // Global error handler
171
+ process.on('unhandledRejection', (error) => {
172
+ console.error('ERROR: Unhandled error:', error);
173
+ process.exit(2);
174
+ });
175
+
176
+ // Parse arguments
177
+ program.parse(process.argv);
178
+
179
+ // Show help if no command provided
180
+ if (!process.argv.slice(2).length) {
181
+ program.outputHelp();
182
+ process.exit(0);
183
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * shipit check command - Validate ShipIt installation
3
+ */
4
+
5
+ import { existsSync, readFileSync } from 'fs';
6
+ import { join, resolve } from 'path';
7
+ import { readManifest } from '../utils/manifest.js';
8
+
9
+ /**
10
+ * Check command implementation
11
+ * @param {object} options - Command options
12
+ */
13
+ export async function checkCommand(options) {
14
+ const projectPath = resolve(options.path || process.cwd());
15
+ const jsonOutput = options.json || false;
16
+
17
+ const manifest = readManifest();
18
+ const status = {
19
+ initialized: false,
20
+ projectJsonExists: false,
21
+ frameworkFiles: {
22
+ present: [],
23
+ missing: []
24
+ },
25
+ version: null,
26
+ userCustomizations: []
27
+ };
28
+
29
+ // Check project.json
30
+ const projectJsonPath = join(projectPath, 'project.json');
31
+ if (existsSync(projectJsonPath)) {
32
+ status.projectJsonExists = true;
33
+ status.initialized = true;
34
+
35
+ try {
36
+ const projectJson = JSON.parse(readFileSync(projectJsonPath, 'utf-8'));
37
+ status.version = projectJson.shipitVersion || null;
38
+ } catch (e) {
39
+ // Ignore parse errors
40
+ }
41
+ }
42
+
43
+ // Check framework files
44
+ for (const file of manifest.frameworkOwned.files || []) {
45
+ const filePath = join(projectPath, file);
46
+ if (existsSync(filePath)) {
47
+ status.frameworkFiles.present.push(file);
48
+ } else {
49
+ status.frameworkFiles.missing.push(file);
50
+ }
51
+ }
52
+
53
+ // Check .override directory
54
+ const overridePath = join(projectPath, '.override');
55
+ if (existsSync(overridePath)) {
56
+ // List files in .override (user customizations)
57
+ // Simplified - just check if directory exists
58
+ status.userCustomizations.push('.override/');
59
+ }
60
+
61
+ // Output results
62
+ if (jsonOutput) {
63
+ console.log(JSON.stringify(status, null, 2));
64
+ } else {
65
+ console.log('ShipIt Installation Check');
66
+ console.log('========================');
67
+ console.log(`Initialized: ${status.initialized ? 'Yes' : 'No'}`);
68
+ if (status.version) {
69
+ console.log(`Version: ${status.version}`);
70
+ }
71
+ console.log(`Framework files present: ${status.frameworkFiles.present.length}`);
72
+ console.log(`Framework files missing: ${status.frameworkFiles.missing.length}`);
73
+ if (status.frameworkFiles.missing.length > 0) {
74
+ console.log('\nMissing files:');
75
+ status.frameworkFiles.missing.forEach(file => console.log(` - ${file}`));
76
+ }
77
+ if (status.userCustomizations.length > 0) {
78
+ console.log('\nUser customizations:');
79
+ status.userCustomizations.forEach(custom => console.log(` - ${custom}`));
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,195 @@
1
+ /**
2
+ * shipit create command - Create new ShipIt project
3
+ */
4
+
5
+ import { existsSync, writeFileSync } from 'fs';
6
+ import fsExtra from 'fs-extra';
7
+
8
+ const { mkdirSync } = fsExtra;
9
+ import { join, resolve } from 'path';
10
+ import { readManifest, getFrameworkRoot } from '../utils/manifest.js';
11
+ import { isValidStack } from '../utils/stack-detection.js';
12
+ import { copyFrameworkFiles } from '../utils/file-copy.js';
13
+ import { createReadlineInterface, promptUser } from '../utils/prompts.js';
14
+ import { execSync } from 'child_process';
15
+ import { getShipitScripts, getShipitDevDependencies } from '../utils/package-json-merge.js';
16
+ import { createTypeScriptNodeFiles, createPythonFiles, createOtherStackFiles, createCIWorkflow } from '../utils/stack-files.js';
17
+
18
+ /**
19
+ * Create command implementation
20
+ * @param {string} projectName - Project name
21
+ * @param {object} options - Command options
22
+ */
23
+ export async function createCommand(projectName, options) {
24
+ const nonInteractive = options.nonInteractive || process.env.SHIPIT_NON_INTERACTIVE === '1';
25
+ const skipGit = options.skipGit || false;
26
+ const skipInstall = options.skipInstall || false;
27
+
28
+ // Validate project name
29
+ if (!/^[a-zA-Z0-9_-]+$/.test(projectName)) {
30
+ throw new Error('Project name must be alphanumeric with hyphens/underscores only');
31
+ }
32
+
33
+ const projectPath = resolve(projectName);
34
+
35
+ // Check if directory exists
36
+ if (existsSync(projectPath)) {
37
+ if (!options.force && !nonInteractive) {
38
+ const rl = createReadlineInterface();
39
+ const answer = await promptUser(rl, `Directory ${projectName} already exists. Continue? (y/N): `);
40
+ rl.close();
41
+ if (answer.toLowerCase() !== 'y') {
42
+ console.log('Aborted.');
43
+ process.exit(0);
44
+ }
45
+ }
46
+ } else {
47
+ mkdirSync(projectPath, { recursive: true });
48
+ }
49
+
50
+ // Get tech stack
51
+ let techStack = options.techStack;
52
+ if (!techStack && !nonInteractive) {
53
+ const rl = createReadlineInterface();
54
+ console.log('Tech stack selection:');
55
+ console.log('1) TypeScript/Node.js (recommended)');
56
+ console.log('2) Python');
57
+ console.log('3) Other (manual setup)');
58
+ const choice = await promptUser(rl, 'Select tech stack [1=TS/Node, 2=Python, 3=Other]: ');
59
+ rl.close();
60
+
61
+ switch (choice.trim()) {
62
+ case '1': techStack = 'typescript-nodejs'; break;
63
+ case '2': techStack = 'python'; break;
64
+ case '3': techStack = 'other'; break;
65
+ default: techStack = 'typescript-nodejs';
66
+ }
67
+ }
68
+ techStack = techStack || 'typescript-nodejs';
69
+
70
+ if (!isValidStack(techStack)) {
71
+ throw new Error(`Invalid tech stack: ${techStack}. Must be typescript-nodejs, python, or other.`);
72
+ }
73
+
74
+ // Get description
75
+ let description = options.description;
76
+ if (!description && !nonInteractive) {
77
+ const rl = createReadlineInterface();
78
+ description = await promptUser(rl, 'Project description (short): ');
79
+ rl.close();
80
+ }
81
+ description = description || projectName;
82
+
83
+ // Get high-risk domains
84
+ let highRisk = options.highRisk;
85
+ if (!highRisk && !nonInteractive) {
86
+ const rl = createReadlineInterface();
87
+ console.log('High-Risk Domains (comma-separated, or "none"):');
88
+ console.log('Examples: auth, payments, permissions, infrastructure, pii');
89
+ highRisk = await promptUser(rl, 'High-risk domains: ');
90
+ rl.close();
91
+ }
92
+ highRisk = highRisk || 'none';
93
+ const highRiskArray = highRisk === 'none' ? [] : highRisk.split(',').map(s => s.trim());
94
+
95
+ console.log(`Creating ShipIt project: ${projectName}`);
96
+ console.log(` Tech stack: ${techStack}`);
97
+ console.log(` Description: ${description}`);
98
+
99
+ // Read manifest
100
+ const manifest = readManifest();
101
+ const frameworkRoot = getFrameworkRoot();
102
+
103
+ // Copy framework files
104
+ console.log('Copying framework files...');
105
+ const copyResult = copyFrameworkFiles(frameworkRoot, projectPath, techStack, manifest, {
106
+ verbose: !nonInteractive
107
+ });
108
+
109
+ if (copyResult.errors.length > 0) {
110
+ console.error('Errors during file copy:');
111
+ copyResult.errors.forEach(err => console.error(` ${err}`));
112
+ throw new Error('Failed to copy some framework files');
113
+ }
114
+
115
+ // Create stack-specific files (package.json, tsconfig.json, etc.)
116
+ if (techStack === 'typescript-nodejs') {
117
+ const shipitScripts = getShipitScripts();
118
+ const shipitDevDeps = getShipitDevDependencies();
119
+ createTypeScriptNodeFiles(projectPath, projectName, description, shipitScripts, shipitDevDeps);
120
+ } else if (techStack === 'python') {
121
+ createPythonFiles(projectPath, projectName, description);
122
+ } else {
123
+ createOtherStackFiles(projectPath);
124
+ }
125
+
126
+ // Create stack-specific CI workflow
127
+ createCIWorkflow(projectPath, techStack);
128
+
129
+ // Create project.json
130
+ const projectJson = {
131
+ name: projectName,
132
+ description: description,
133
+ version: '0.1.0',
134
+ techStack: techStack,
135
+ created: new Date().toISOString(),
136
+ highRiskDomains: highRiskArray,
137
+ settings: {
138
+ humanResponseTime: 'minutes',
139
+ confidenceThreshold: 0.7,
140
+ testCoverageMinimum: 80
141
+ },
142
+ shipitVersion: '1.0.0'
143
+ };
144
+ writeFileSync(
145
+ join(projectPath, 'project.json'),
146
+ JSON.stringify(projectJson, null, 2) + '\n',
147
+ 'utf-8'
148
+ );
149
+
150
+ // Create .override directory structure
151
+ const overrideDirs = [
152
+ '.override/rules',
153
+ '.override/commands',
154
+ '.override/scripts',
155
+ '.override/config'
156
+ ];
157
+ for (const dir of overrideDirs) {
158
+ const dirPath = join(projectPath, dir);
159
+ if (!existsSync(dirPath)) {
160
+ mkdirSync(dirPath, { recursive: true });
161
+ }
162
+ }
163
+
164
+ // Initialize git
165
+ if (!skipGit) {
166
+ const gitPath = join(projectPath, '.git');
167
+ if (!existsSync(gitPath)) {
168
+ console.log('Initializing git repository...');
169
+ try {
170
+ execSync('git init', { cwd: projectPath, stdio: 'inherit' });
171
+ execSync('git add .', { cwd: projectPath, stdio: 'inherit' });
172
+ execSync('git commit -m "Initial commit: ' + projectName + '"', { cwd: projectPath, stdio: 'inherit' });
173
+ } catch (error) {
174
+ console.warn('Warning: Git initialization failed (git may not be installed)');
175
+ }
176
+ }
177
+ }
178
+
179
+ // Run package manager install
180
+ if (!skipInstall && techStack === 'typescript-nodejs') {
181
+ console.log('Installing dependencies...');
182
+ try {
183
+ execSync('pnpm install', { cwd: projectPath, stdio: 'inherit' });
184
+ } catch (error) {
185
+ console.warn('Warning: Package installation failed');
186
+ }
187
+ }
188
+
189
+ console.log('\n✓ Project created successfully!');
190
+ console.log(`\nNext steps:`);
191
+ console.log(`1. cd ${projectName}`);
192
+ console.log('2. Run /scope-project to break down into features');
193
+ console.log('3. Start creating intents with /new_intent');
194
+ }
195
+