@nolrm/contextkit 0.13.5 → 0.14.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/README.md +78 -47
- package/bin/contextkit.js +22 -2
- package/lib/commands/analyze.js +131 -91
- package/lib/commands/check.js +24 -18
- package/lib/commands/gates.js +119 -0
- package/lib/commands/install.js +447 -142
- package/lib/commands/note.js +12 -20
- package/lib/commands/run.js +20 -22
- package/lib/commands/status.js +61 -32
- package/lib/commands/update.js +119 -80
- package/lib/index.js +3 -1
- package/lib/integrations/aider-integration.js +1 -1
- package/lib/integrations/base-integration.js +13 -6
- package/lib/integrations/claude-integration.js +103 -41
- package/lib/integrations/continue-integration.js +5 -5
- package/lib/integrations/copilot-integration.js +1 -1
- package/lib/integrations/cursor-integration.js +70 -28
- package/lib/integrations/gemini-integration.js +13 -11
- package/lib/integrations/index.js +11 -1
- package/lib/utils/banner.js +14 -11
- package/lib/utils/download.js +3 -4
- package/lib/utils/git-hooks.js +3 -4
- package/lib/utils/migrations.js +6 -4
- package/lib/utils/migrations.md +4 -3
- package/lib/utils/notifier.js +1 -1
- package/lib/utils/project-detector.js +11 -5
- package/lib/utils/status-manager.js +6 -7
- package/lib/utils/tool-detector.js +19 -21
- package/package.json +8 -2
package/lib/commands/install.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
-
const ora = require('ora');
|
|
3
2
|
const inquirer = require('inquirer');
|
|
4
3
|
const fs = require('fs-extra');
|
|
5
4
|
const path = require('path');
|
|
6
|
-
const
|
|
5
|
+
const childProcess = require('child_process');
|
|
7
6
|
|
|
8
7
|
const DownloadManager = require('../utils/download');
|
|
9
8
|
const ProjectDetector = require('../utils/project-detector');
|
|
@@ -22,7 +21,7 @@ class InstallCommand {
|
|
|
22
21
|
|
|
23
22
|
async install(options = {}) {
|
|
24
23
|
// Migrate legacy .vibe-kit/ directory
|
|
25
|
-
if (await fs.pathExists('.vibe-kit') && !await fs.pathExists('.contextkit')) {
|
|
24
|
+
if ((await fs.pathExists('.vibe-kit')) && !(await fs.pathExists('.contextkit'))) {
|
|
26
25
|
console.log(chalk.yellow('Found legacy .vibe-kit/ directory'));
|
|
27
26
|
console.log(chalk.yellow('Renaming to .contextkit/...'));
|
|
28
27
|
await fs.move('.vibe-kit', '.contextkit');
|
|
@@ -41,8 +40,12 @@ class InstallCommand {
|
|
|
41
40
|
const hasGit = await this._findFileUpward('.git', 3);
|
|
42
41
|
const hasPkg = await fs.pathExists('package.json');
|
|
43
42
|
if (!hasGit && !hasPkg) {
|
|
44
|
-
console.log(
|
|
45
|
-
|
|
43
|
+
console.log(
|
|
44
|
+
chalk.yellow('⚠️ No project detected (no .git or package.json found in this directory).')
|
|
45
|
+
);
|
|
46
|
+
console.log(
|
|
47
|
+
chalk.yellow(' Make sure you are inside your project before running `ck install`.')
|
|
48
|
+
);
|
|
46
49
|
console.log('');
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -87,7 +90,9 @@ class InstallCommand {
|
|
|
87
90
|
const { shouldContinue } = await this.promptReinstall();
|
|
88
91
|
if (!shouldContinue) {
|
|
89
92
|
console.log(chalk.yellow('⏭️ Installation cancelled'));
|
|
90
|
-
console.log(
|
|
93
|
+
console.log(
|
|
94
|
+
chalk.dim('💡 To get the latest command and squad files, run: ') + chalk.cyan('ck update')
|
|
95
|
+
);
|
|
91
96
|
return;
|
|
92
97
|
}
|
|
93
98
|
}
|
|
@@ -114,6 +119,11 @@ class InstallCommand {
|
|
|
114
119
|
await this.gitHooksManager.installHooks(packageManager, hookChoices);
|
|
115
120
|
}
|
|
116
121
|
|
|
122
|
+
// Offer quality tooling scaffold for Node.js projects with pre-push enabled
|
|
123
|
+
if (hookChoices.prePush && !options.nonInteractive) {
|
|
124
|
+
await this.promptQualityTooling(packageManager, options);
|
|
125
|
+
}
|
|
126
|
+
|
|
117
127
|
// Ask about GitHub Actions CI squad workflow
|
|
118
128
|
let squadCi = false;
|
|
119
129
|
if (!options.nonInteractive) {
|
|
@@ -123,6 +133,9 @@ class InstallCommand {
|
|
|
123
133
|
await this.installGitHubActionsWorkflow();
|
|
124
134
|
}
|
|
125
135
|
|
|
136
|
+
// Create quality gates config
|
|
137
|
+
await this.createQualityGatesConfig();
|
|
138
|
+
|
|
126
139
|
// Create configuration
|
|
127
140
|
await this.createConfiguration(projectType, hookChoices, squadCi);
|
|
128
141
|
|
|
@@ -151,7 +164,11 @@ class InstallCommand {
|
|
|
151
164
|
|
|
152
165
|
if (!integration) {
|
|
153
166
|
console.log(chalk.red(`❌ Unknown platform: ${platform}`));
|
|
154
|
-
console.log(
|
|
167
|
+
console.log(
|
|
168
|
+
chalk.yellow(
|
|
169
|
+
'💡 Available: claude, cursor, copilot, codex, opencode, gemini, aider, continue, windsurf'
|
|
170
|
+
)
|
|
171
|
+
);
|
|
155
172
|
return;
|
|
156
173
|
}
|
|
157
174
|
|
|
@@ -161,7 +178,6 @@ class InstallCommand {
|
|
|
161
178
|
console.log(chalk.green(`🎉 ${integration.displayName} integration installed!`));
|
|
162
179
|
|
|
163
180
|
integration.showUsage();
|
|
164
|
-
|
|
165
181
|
} catch (error) {
|
|
166
182
|
console.log(chalk.red(`❌ Failed to install ${platform} integration`));
|
|
167
183
|
console.log(chalk.yellow(error.message));
|
|
@@ -186,30 +202,32 @@ class InstallCommand {
|
|
|
186
202
|
type: 'confirm',
|
|
187
203
|
name: 'shouldContinue',
|
|
188
204
|
message: 'ContextKit is already installed. Do you want to reinstall?',
|
|
189
|
-
default: false
|
|
190
|
-
}
|
|
205
|
+
default: false,
|
|
206
|
+
},
|
|
191
207
|
]);
|
|
192
208
|
return { shouldContinue };
|
|
193
209
|
}
|
|
194
210
|
|
|
195
211
|
async promptPlatformChoice() {
|
|
196
|
-
const { platform } = await inquirer.prompt([
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
212
|
+
const { platform } = await inquirer.prompt([
|
|
213
|
+
{
|
|
214
|
+
type: 'list',
|
|
215
|
+
name: 'platform',
|
|
216
|
+
message: 'Which AI tool are you using?',
|
|
217
|
+
choices: [
|
|
218
|
+
{ name: 'Claude Code', value: 'claude' },
|
|
219
|
+
{ name: 'Cursor', value: 'cursor' },
|
|
220
|
+
{ name: 'Copilot (GitHub)', value: 'copilot' },
|
|
221
|
+
{ name: 'Codex (OpenAI)', value: 'codex' },
|
|
222
|
+
{ name: 'OpenCode', value: 'opencode' },
|
|
223
|
+
{ name: 'Gemini', value: 'gemini' },
|
|
224
|
+
{ name: 'Windsurf', value: 'windsurf' },
|
|
225
|
+
{ name: 'Aider', value: 'aider' },
|
|
226
|
+
{ name: 'Continue', value: 'continue' },
|
|
227
|
+
{ name: 'Skip (base only)', value: null },
|
|
228
|
+
],
|
|
229
|
+
},
|
|
230
|
+
]);
|
|
213
231
|
return platform;
|
|
214
232
|
}
|
|
215
233
|
|
|
@@ -257,7 +275,9 @@ class InstallCommand {
|
|
|
257
275
|
`${this.repoUrl}/templates/github-actions/squad-issue.yml`,
|
|
258
276
|
'.github/workflows/squad-issue.yml'
|
|
259
277
|
);
|
|
260
|
-
console.log(
|
|
278
|
+
console.log(
|
|
279
|
+
chalk.green('✅ CI squad workflow installed → .github/workflows/squad-issue.yml')
|
|
280
|
+
);
|
|
261
281
|
} catch (error) {
|
|
262
282
|
console.log(chalk.yellow('⚠️ Could not install CI squad workflow:'), error.message);
|
|
263
283
|
}
|
|
@@ -270,7 +290,7 @@ class InstallCommand {
|
|
|
270
290
|
return { prePush: false, commitMsg: false };
|
|
271
291
|
}
|
|
272
292
|
|
|
273
|
-
if (!await fs.pathExists('.git')) {
|
|
293
|
+
if (!(await fs.pathExists('.git'))) {
|
|
274
294
|
console.log(chalk.yellow('⚠️ Skipping Git hooks setup (not a git repository)'));
|
|
275
295
|
return { prePush: false, commitMsg: false };
|
|
276
296
|
}
|
|
@@ -291,8 +311,8 @@ class InstallCommand {
|
|
|
291
311
|
type: 'confirm',
|
|
292
312
|
name: 'prePush',
|
|
293
313
|
message: 'Enable pre-push hook? (runs quality checks before push)',
|
|
294
|
-
default: false
|
|
295
|
-
}
|
|
314
|
+
default: false,
|
|
315
|
+
},
|
|
296
316
|
]);
|
|
297
317
|
|
|
298
318
|
if (prePush) {
|
|
@@ -314,8 +334,8 @@ class InstallCommand {
|
|
|
314
334
|
type: 'confirm',
|
|
315
335
|
name: 'commitMsg',
|
|
316
336
|
message: 'Enable commit-msg hook? (enforces conventional commit format)',
|
|
317
|
-
default: false
|
|
318
|
-
}
|
|
337
|
+
default: false,
|
|
338
|
+
},
|
|
319
339
|
]);
|
|
320
340
|
|
|
321
341
|
if (commitMsg) {
|
|
@@ -336,7 +356,7 @@ class InstallCommand {
|
|
|
336
356
|
|
|
337
357
|
async createDirectoryStructure() {
|
|
338
358
|
console.log(chalk.blue('📁 Creating structure...'));
|
|
339
|
-
|
|
359
|
+
|
|
340
360
|
const directories = [
|
|
341
361
|
'.contextkit/standards',
|
|
342
362
|
'.contextkit/standards/code-style', // Granular code style files
|
|
@@ -350,7 +370,7 @@ class InstallCommand {
|
|
|
350
370
|
'.contextkit/templates',
|
|
351
371
|
'.contextkit/scripts',
|
|
352
372
|
'.contextkit/integrations',
|
|
353
|
-
'.contextkit/policies' // Policy enforcement configs
|
|
373
|
+
'.contextkit/policies', // Policy enforcement configs
|
|
354
374
|
];
|
|
355
375
|
|
|
356
376
|
for (const dir of directories) {
|
|
@@ -393,7 +413,7 @@ Use conditional loading tags:
|
|
|
393
413
|
[TypeScript-specific content]
|
|
394
414
|
\`\`\`
|
|
395
415
|
`,
|
|
396
|
-
|
|
416
|
+
|
|
397
417
|
'standards/testing.md': `# Testing Standards
|
|
398
418
|
|
|
399
419
|
<!-- Content will be generated by running: /analyze -->
|
|
@@ -428,7 +448,7 @@ describe("ComponentName", () => {
|
|
|
428
448
|
- Consistent organization across all test files
|
|
429
449
|
- Quick debugging and maintenance
|
|
430
450
|
`,
|
|
431
|
-
|
|
451
|
+
|
|
432
452
|
'standards/architecture.md': `# Architecture
|
|
433
453
|
|
|
434
454
|
## Documentation Levels
|
|
@@ -476,22 +496,54 @@ Documentation for a single component or a small, cohesive set of components.
|
|
|
476
496
|
Your architecture patterns will be documented based on your project structure and organization.
|
|
477
497
|
|
|
478
498
|
Run \`/analyze\` to generate this content.`,
|
|
479
|
-
|
|
499
|
+
|
|
480
500
|
'standards/ai-guidelines.md': `# AI Guidelines
|
|
481
501
|
|
|
482
|
-
|
|
502
|
+
> Run \`/analyze\` to add project-specific rules to this file.
|
|
483
503
|
|
|
484
|
-
|
|
504
|
+
## Agentic Workflow
|
|
505
|
+
|
|
506
|
+
When working as an agent in this project:
|
|
507
|
+
|
|
508
|
+
- **Read standards first** — load \`code-style.md\` and \`testing.md\` before writing code
|
|
509
|
+
- **Before pushing** — run through \`.contextkit/commands/agents/agent-push-checklist.md\`
|
|
510
|
+
- **Commit format** — all commits must follow Conventional Commits: \`type(scope): description\`
|
|
511
|
+
- Valid types: \`feat\`, \`fix\`, \`improve\`, \`docs\`, \`chore\`, \`refactor\`, \`test\`
|
|
512
|
+
- **When to proceed** — proceed if the task is clear and standards cover it
|
|
513
|
+
- **When to ask** — ask if the task is ambiguous, contradicts existing standards, or requires an architecture decision
|
|
514
|
+
- **No debug statements** — do not leave \`console.log\`, \`print\`, or equivalent debug output in production code
|
|
515
|
+
|
|
516
|
+
## Context Budget
|
|
517
|
+
|
|
518
|
+
Load standards files in this priority order to use your context window efficiently:
|
|
519
|
+
|
|
520
|
+
1. **Always load:** \`code-style.md\`, \`testing.md\` — highest signal, always relevant
|
|
521
|
+
2. **Load at session start:** \`ai-guidelines.md\` (this file) — behaviour rules
|
|
522
|
+
3. **Load on demand:** \`architecture.md\` — only when making structural decisions
|
|
523
|
+
4. **Load on demand:** \`workflows.md\` — only for process questions
|
|
524
|
+
5. **Load selectively:** \`code-style/typescript-style.md\`, \`code-style/css-style.md\` — only for the file type you are editing
|
|
525
|
+
6. **Skip unless needed:** \`glossary.md\` — only when the task involves domain-specific terms
|
|
526
|
+
|
|
527
|
+
If a standards file is longer than 200 lines, read the sections relevant to your task — not the whole file.
|
|
528
|
+
|
|
529
|
+
## Standards Loop
|
|
530
|
+
|
|
531
|
+
This project follows a continuous standards loop:
|
|
532
|
+
|
|
533
|
+
1. Standards files define what correct looks like
|
|
534
|
+
2. Quality gates enforce it at every push (human or agent)
|
|
535
|
+
3. Agents read standards before writing code and write to standards when new patterns emerge
|
|
536
|
+
|
|
537
|
+
When you discover a pattern worth standardising, use \`/standards-aware\` to decide whether and how to add it.
|
|
538
|
+
Without the standards, agents guess. Without the gates, the guesses reach the repo unchecked.`,
|
|
485
539
|
|
|
486
|
-
Run \`/analyze\` to generate this content.`,
|
|
487
|
-
|
|
488
540
|
'standards/workflows.md': `# Workflows
|
|
489
541
|
|
|
490
542
|
<!-- Content will be generated by running: /analyze -->
|
|
491
543
|
|
|
492
544
|
Development workflows and processes will be documented based on your project's practices.
|
|
493
545
|
|
|
494
|
-
Run \`/analyze\` to generate this content
|
|
546
|
+
Run \`/analyze\` to generate this content.`,
|
|
495
547
|
};
|
|
496
548
|
|
|
497
549
|
// Create granular code-style skeleton files
|
|
@@ -562,7 +614,7 @@ This file is loaded when HTML-related tasks are detected:
|
|
|
562
614
|
<!-- when:html -->
|
|
563
615
|
[HTML-specific content]
|
|
564
616
|
\`\`\`
|
|
565
|
-
|
|
617
|
+
`,
|
|
566
618
|
};
|
|
567
619
|
|
|
568
620
|
for (const [relativePath, content] of Object.entries(skeletonFiles)) {
|
|
@@ -688,7 +740,7 @@ Main paths through this feature:
|
|
|
688
740
|
## Notes
|
|
689
741
|
|
|
690
742
|
Any design decisions, trade-offs, or open questions to resolve before coding.
|
|
691
|
-
|
|
743
|
+
`,
|
|
692
744
|
};
|
|
693
745
|
|
|
694
746
|
for (const [relativePath, content] of Object.entries(skeletonFiles)) {
|
|
@@ -696,22 +748,22 @@ Any design decisions, trade-offs, or open questions to resolve before coding.
|
|
|
696
748
|
}
|
|
697
749
|
}
|
|
698
750
|
|
|
699
|
-
async downloadFiles(projectType,
|
|
751
|
+
async downloadFiles(projectType, _options = {}) {
|
|
700
752
|
try {
|
|
701
753
|
// Create skeleton standards files (will be customized by analyze)
|
|
702
754
|
console.log(chalk.blue('📝 Creating skeleton standards files...'));
|
|
703
755
|
await this.createSkeletonStandards();
|
|
704
|
-
|
|
756
|
+
|
|
705
757
|
console.log(chalk.green('✅ Skeleton files created'));
|
|
706
758
|
console.log(chalk.yellow('💡 Run: /analyze to generate content based on your codebase'));
|
|
707
759
|
console.log('');
|
|
708
|
-
|
|
760
|
+
|
|
709
761
|
// Download base files
|
|
710
762
|
await this.downloadManager.downloadFile(
|
|
711
763
|
`${this.repoUrl}/standards/README.md`,
|
|
712
764
|
'.contextkit/standards/README.md'
|
|
713
765
|
);
|
|
714
|
-
|
|
766
|
+
|
|
715
767
|
// Download the actual glossary (keep it as-is, universal across all projects)
|
|
716
768
|
await this.downloadManager.downloadFile(
|
|
717
769
|
`${this.repoUrl}/standards/glossary.md`,
|
|
@@ -720,104 +772,118 @@ Any design decisions, trade-offs, or open questions to resolve before coding.
|
|
|
720
772
|
|
|
721
773
|
// Download commands
|
|
722
774
|
await this.downloadManager.downloadFile(
|
|
723
|
-
`${this.repoUrl}/commands/analyze.md`,
|
|
724
|
-
'.contextkit/commands/analyze.md'
|
|
775
|
+
`${this.repoUrl}/commands/dev/analyze.md`,
|
|
776
|
+
'.contextkit/commands/dev/analyze.md'
|
|
725
777
|
);
|
|
726
778
|
await this.downloadManager.downloadFile(
|
|
727
|
-
`${this.repoUrl}/commands/review.md`,
|
|
728
|
-
'.contextkit/commands/review.md'
|
|
779
|
+
`${this.repoUrl}/commands/dev/review.md`,
|
|
780
|
+
'.contextkit/commands/dev/review.md'
|
|
729
781
|
);
|
|
730
782
|
await this.downloadManager.downloadFile(
|
|
731
|
-
`${this.repoUrl}/commands/fix.md`,
|
|
732
|
-
'.contextkit/commands/fix.md'
|
|
783
|
+
`${this.repoUrl}/commands/dev/fix.md`,
|
|
784
|
+
'.contextkit/commands/dev/fix.md'
|
|
733
785
|
);
|
|
734
786
|
await this.downloadManager.downloadFile(
|
|
735
|
-
`${this.repoUrl}/commands/refactor.md`,
|
|
736
|
-
'.contextkit/commands/refactor.md'
|
|
787
|
+
`${this.repoUrl}/commands/dev/refactor.md`,
|
|
788
|
+
'.contextkit/commands/dev/refactor.md'
|
|
737
789
|
);
|
|
738
790
|
await this.downloadManager.downloadFile(
|
|
739
|
-
`${this.repoUrl}/commands/run-tests.md`,
|
|
740
|
-
'.contextkit/commands/run-tests.md'
|
|
791
|
+
`${this.repoUrl}/commands/dev/run-tests.md`,
|
|
792
|
+
'.contextkit/commands/dev/run-tests.md'
|
|
741
793
|
);
|
|
742
794
|
await this.downloadManager.downloadFile(
|
|
743
|
-
`${this.repoUrl}/commands/add-documentation.md`,
|
|
744
|
-
'.contextkit/commands/add-documentation.md'
|
|
795
|
+
`${this.repoUrl}/commands/docs/add-documentation.md`,
|
|
796
|
+
'.contextkit/commands/docs/add-documentation.md'
|
|
745
797
|
);
|
|
746
798
|
await this.downloadManager.downloadFile(
|
|
747
|
-
`${this.repoUrl}/commands/quality-check.md`,
|
|
748
|
-
'.contextkit/commands/quality-check.md'
|
|
799
|
+
`${this.repoUrl}/commands/dev/quality-check.md`,
|
|
800
|
+
'.contextkit/commands/dev/quality-check.md'
|
|
749
801
|
);
|
|
750
802
|
await this.downloadManager.downloadFile(
|
|
751
|
-
`${this.repoUrl}/commands/create-feature.md`,
|
|
752
|
-
'.contextkit/commands/create-feature.md'
|
|
803
|
+
`${this.repoUrl}/commands/dev/create-feature.md`,
|
|
804
|
+
'.contextkit/commands/dev/create-feature.md'
|
|
753
805
|
);
|
|
754
806
|
await this.downloadManager.downloadFile(
|
|
755
|
-
`${this.repoUrl}/commands/create-component.md`,
|
|
756
|
-
'.contextkit/commands/create-component.md'
|
|
807
|
+
`${this.repoUrl}/commands/dev/create-component.md`,
|
|
808
|
+
'.contextkit/commands/dev/create-component.md'
|
|
757
809
|
);
|
|
758
810
|
await this.downloadManager.downloadFile(
|
|
759
|
-
`${this.repoUrl}/commands/spec.md`,
|
|
760
|
-
'.contextkit/commands/spec.md'
|
|
811
|
+
`${this.repoUrl}/commands/dev/spec.md`,
|
|
812
|
+
'.contextkit/commands/dev/spec.md'
|
|
761
813
|
);
|
|
762
814
|
|
|
763
815
|
// Download squad commands
|
|
764
816
|
await this.downloadManager.downloadFile(
|
|
765
|
-
`${this.repoUrl}/commands/squad.md`,
|
|
766
|
-
'.contextkit/commands/squad.md'
|
|
817
|
+
`${this.repoUrl}/commands/squad/squad.md`,
|
|
818
|
+
'.contextkit/commands/squad/squad.md'
|
|
767
819
|
);
|
|
768
820
|
await this.downloadManager.downloadFile(
|
|
769
|
-
`${this.repoUrl}/commands/squad-architect.md`,
|
|
770
|
-
'.contextkit/commands/squad-architect.md'
|
|
821
|
+
`${this.repoUrl}/commands/squad/squad-architect.md`,
|
|
822
|
+
'.contextkit/commands/squad/squad-architect.md'
|
|
771
823
|
);
|
|
772
824
|
await this.downloadManager.downloadFile(
|
|
773
|
-
`${this.repoUrl}/commands/squad-dev.md`,
|
|
774
|
-
'.contextkit/commands/squad-dev.md'
|
|
825
|
+
`${this.repoUrl}/commands/squad/squad-dev.md`,
|
|
826
|
+
'.contextkit/commands/squad/squad-dev.md'
|
|
775
827
|
);
|
|
776
828
|
await this.downloadManager.downloadFile(
|
|
777
|
-
`${this.repoUrl}/commands/squad-test.md`,
|
|
778
|
-
'.contextkit/commands/squad-test.md'
|
|
829
|
+
`${this.repoUrl}/commands/squad/squad-test.md`,
|
|
830
|
+
'.contextkit/commands/squad/squad-test.md'
|
|
779
831
|
);
|
|
780
832
|
await this.downloadManager.downloadFile(
|
|
781
|
-
`${this.repoUrl}/commands/squad-review.md`,
|
|
782
|
-
'.contextkit/commands/squad-review.md'
|
|
833
|
+
`${this.repoUrl}/commands/squad/squad-review.md`,
|
|
834
|
+
'.contextkit/commands/squad/squad-review.md'
|
|
783
835
|
);
|
|
784
836
|
await this.downloadManager.downloadFile(
|
|
785
|
-
`${this.repoUrl}/commands/squad-auto.md`,
|
|
786
|
-
'.contextkit/commands/squad-auto.md'
|
|
837
|
+
`${this.repoUrl}/commands/squad/squad-auto.md`,
|
|
838
|
+
'.contextkit/commands/squad/squad-auto.md'
|
|
787
839
|
);
|
|
788
840
|
await this.downloadManager.downloadFile(
|
|
789
|
-
`${this.repoUrl}/commands/squad-auto-parallel.md`,
|
|
790
|
-
'.contextkit/commands/squad-auto-parallel.md'
|
|
841
|
+
`${this.repoUrl}/commands/squad/squad-auto-parallel.md`,
|
|
842
|
+
'.contextkit/commands/squad/squad-auto-parallel.md'
|
|
791
843
|
);
|
|
792
844
|
await this.downloadManager.downloadFile(
|
|
793
|
-
`${this.repoUrl}/commands/squad-reset.md`,
|
|
794
|
-
'.contextkit/commands/squad-reset.md'
|
|
845
|
+
`${this.repoUrl}/commands/squad/squad-reset.md`,
|
|
846
|
+
'.contextkit/commands/squad/squad-reset.md'
|
|
795
847
|
);
|
|
796
848
|
await this.downloadManager.downloadFile(
|
|
797
|
-
`${this.repoUrl}/commands/squad-doc.md`,
|
|
798
|
-
'.contextkit/commands/squad-doc.md'
|
|
849
|
+
`${this.repoUrl}/commands/squad/squad-doc.md`,
|
|
850
|
+
'.contextkit/commands/squad/squad-doc.md'
|
|
799
851
|
);
|
|
800
852
|
await this.downloadManager.downloadFile(
|
|
801
|
-
`${this.repoUrl}/commands/squad-ci.md`,
|
|
802
|
-
'.contextkit/commands/squad-ci.md'
|
|
853
|
+
`${this.repoUrl}/commands/squad/squad-ci.md`,
|
|
854
|
+
'.contextkit/commands/squad/squad-ci.md'
|
|
803
855
|
);
|
|
804
856
|
await this.downloadManager.downloadFile(
|
|
805
|
-
`${this.repoUrl}/commands/health-check.md`,
|
|
806
|
-
'.contextkit/commands/health-check.md'
|
|
857
|
+
`${this.repoUrl}/commands/dev/health-check.md`,
|
|
858
|
+
'.contextkit/commands/dev/health-check.md'
|
|
807
859
|
);
|
|
808
860
|
|
|
809
861
|
// Download doc family commands
|
|
810
862
|
await this.downloadManager.downloadFile(
|
|
811
|
-
`${this.repoUrl}/commands/doc-arch.md`,
|
|
812
|
-
'.contextkit/commands/doc-arch.md'
|
|
863
|
+
`${this.repoUrl}/commands/docs/doc-arch.md`,
|
|
864
|
+
'.contextkit/commands/docs/doc-arch.md'
|
|
865
|
+
);
|
|
866
|
+
await this.downloadManager.downloadFile(
|
|
867
|
+
`${this.repoUrl}/commands/docs/doc-feature.md`,
|
|
868
|
+
'.contextkit/commands/docs/doc-feature.md'
|
|
813
869
|
);
|
|
814
870
|
await this.downloadManager.downloadFile(
|
|
815
|
-
`${this.repoUrl}/commands/doc-
|
|
816
|
-
'.contextkit/commands/doc-
|
|
871
|
+
`${this.repoUrl}/commands/docs/doc-component.md`,
|
|
872
|
+
'.contextkit/commands/docs/doc-component.md'
|
|
873
|
+
);
|
|
874
|
+
|
|
875
|
+
// Download agentic workflow commands
|
|
876
|
+
await this.downloadManager.downloadFile(
|
|
877
|
+
`${this.repoUrl}/commands/agents/context-budget.md`,
|
|
878
|
+
'.contextkit/commands/agents/context-budget.md'
|
|
879
|
+
);
|
|
880
|
+
await this.downloadManager.downloadFile(
|
|
881
|
+
`${this.repoUrl}/commands/agents/agent-push-checklist.md`,
|
|
882
|
+
'.contextkit/commands/agents/agent-push-checklist.md'
|
|
817
883
|
);
|
|
818
884
|
await this.downloadManager.downloadFile(
|
|
819
|
-
`${this.repoUrl}/commands/
|
|
820
|
-
'.contextkit/commands/
|
|
885
|
+
`${this.repoUrl}/commands/agents/standards-aware.md`,
|
|
886
|
+
'.contextkit/commands/agents/standards-aware.md'
|
|
821
887
|
);
|
|
822
888
|
|
|
823
889
|
// Download hooks (pre-push and commit-msg only, no pre-commit)
|
|
@@ -920,15 +986,15 @@ claude "read .contextkit/context.md to see available standards, then create a bu
|
|
|
920
986
|
- \`.contextkit/product/context.md\` - Domain-specific context
|
|
921
987
|
|
|
922
988
|
### Commands
|
|
923
|
-
- \`.contextkit/commands/analyze.md\` - Analyze & customize standards
|
|
924
|
-
- \`.contextkit/commands/review.md\` - Code review
|
|
925
|
-
- \`.contextkit/commands/fix.md\` - Diagnose and fix bugs
|
|
926
|
-
- \`.contextkit/commands/refactor.md\` - Refactor code structure
|
|
927
|
-
- \`.contextkit/commands/run-tests.md\` - Generate or run tests
|
|
928
|
-
- \`.contextkit/commands/add-documentation.md\` - Add documentation
|
|
929
|
-
- \`.contextkit/commands/quality-check.md\` - Quality checks
|
|
930
|
-
- \`.contextkit/commands/create-component.md\` - Create component
|
|
931
|
-
- \`.contextkit/commands/create-feature.md\` - Create feature
|
|
989
|
+
- \`.contextkit/commands/dev/analyze.md\` - Analyze & customize standards
|
|
990
|
+
- \`.contextkit/commands/dev/review.md\` - Code review
|
|
991
|
+
- \`.contextkit/commands/dev/fix.md\` - Diagnose and fix bugs
|
|
992
|
+
- \`.contextkit/commands/dev/refactor.md\` - Refactor code structure
|
|
993
|
+
- \`.contextkit/commands/dev/run-tests.md\` - Generate or run tests
|
|
994
|
+
- \`.contextkit/commands/docs/add-documentation.md\` - Add documentation
|
|
995
|
+
- \`.contextkit/commands/dev/quality-check.md\` - Quality checks
|
|
996
|
+
- \`.contextkit/commands/dev/create-component.md\` - Create component
|
|
997
|
+
- \`.contextkit/commands/dev/create-feature.md\` - Create feature
|
|
932
998
|
|
|
933
999
|
### Instructions
|
|
934
1000
|
- \`.contextkit/instructions/meta/pre-flight.md\` - Pre-flight checks
|
|
@@ -982,7 +1048,7 @@ claude "read .contextkit/standards/README.md .contextkit/standards/glossary.md a
|
|
|
982
1048
|
claude "read .contextkit/product/mission-lite.md .contextkit/standards/code-style.md and create a feature"
|
|
983
1049
|
\`\`\`
|
|
984
1050
|
`;
|
|
985
|
-
|
|
1051
|
+
|
|
986
1052
|
await fs.writeFile('.contextkit/context.md', context);
|
|
987
1053
|
await fs.writeFile('.contextkit/CONTEXT.md', context); // Keep uppercase for backward compatibility
|
|
988
1054
|
|
|
@@ -993,14 +1059,14 @@ claude "read .contextkit/product/mission-lite.md .contextkit/standards/code-styl
|
|
|
993
1059
|
|
|
994
1060
|
CONTEXT_FILE=".contextkit/context.md"
|
|
995
1061
|
AI_TOOL="\${AI_TOOL:-aider}"
|
|
996
|
-
PROMPT="
|
|
1062
|
+
PROMPT="$@"
|
|
997
1063
|
|
|
998
1064
|
if [ ! -f "$CONTEXT_FILE" ]; then
|
|
999
1065
|
echo "❌ ContextKit not initialized. Run: contextkit install"
|
|
1000
1066
|
exit 1
|
|
1001
1067
|
fi
|
|
1002
1068
|
|
|
1003
|
-
CONTEXT
|
|
1069
|
+
CONTEXT=$(cat "$CONTEXT_FILE")
|
|
1004
1070
|
|
|
1005
1071
|
case "$AI_TOOL" in
|
|
1006
1072
|
"aider")
|
|
@@ -1021,7 +1087,7 @@ esac
|
|
|
1021
1087
|
|
|
1022
1088
|
await fs.writeFile('.contextkit/scripts/ai-cli.sh', cliScript);
|
|
1023
1089
|
await fs.chmod('.contextkit/scripts/ai-cli.sh', '755');
|
|
1024
|
-
|
|
1090
|
+
|
|
1025
1091
|
console.log(chalk.green('✅ CLI helpers installed'));
|
|
1026
1092
|
}
|
|
1027
1093
|
|
|
@@ -1046,27 +1112,30 @@ esac
|
|
|
1046
1112
|
components: 'src/components',
|
|
1047
1113
|
tests: 'src/__tests__',
|
|
1048
1114
|
stories: 'src/stories',
|
|
1049
|
-
docs: 'docs'
|
|
1115
|
+
docs: 'docs',
|
|
1050
1116
|
},
|
|
1051
1117
|
commands: {
|
|
1052
|
-
analyze: '@.contextkit/commands/analyze.md',
|
|
1053
|
-
review: '@.contextkit/commands/review.md',
|
|
1054
|
-
fix: '@.contextkit/commands/fix.md',
|
|
1055
|
-
refactor: '@.contextkit/commands/refactor.md',
|
|
1056
|
-
run_tests: '@.contextkit/commands/run-tests.md',
|
|
1057
|
-
add_docs: '@.contextkit/commands/add-documentation.md',
|
|
1058
|
-
quality_check: '@.contextkit/commands/quality-check.md',
|
|
1059
|
-
create_component: '@.contextkit/commands/create-component.md',
|
|
1060
|
-
create_feature: '@.contextkit/commands/create-feature.md'
|
|
1061
|
-
}
|
|
1118
|
+
analyze: '@.contextkit/commands/dev/analyze.md',
|
|
1119
|
+
review: '@.contextkit/commands/dev/review.md',
|
|
1120
|
+
fix: '@.contextkit/commands/dev/fix.md',
|
|
1121
|
+
refactor: '@.contextkit/commands/dev/refactor.md',
|
|
1122
|
+
run_tests: '@.contextkit/commands/dev/run-tests.md',
|
|
1123
|
+
add_docs: '@.contextkit/commands/docs/add-documentation.md',
|
|
1124
|
+
quality_check: '@.contextkit/commands/dev/quality-check.md',
|
|
1125
|
+
create_component: '@.contextkit/commands/dev/create-component.md',
|
|
1126
|
+
create_feature: '@.contextkit/commands/dev/create-feature.md',
|
|
1127
|
+
},
|
|
1062
1128
|
};
|
|
1063
1129
|
|
|
1064
1130
|
const now = new Date().toISOString();
|
|
1065
|
-
const isMonorepo =
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1131
|
+
const isMonorepo =
|
|
1132
|
+
(await fs.pathExists('packages')) ||
|
|
1133
|
+
(await fs.pathExists('apps')) ||
|
|
1134
|
+
((await fs.pathExists('package.json')) &&
|
|
1135
|
+
(await fs.readJson('package.json').catch(() => ({}))).workspaces);
|
|
1136
|
+
|
|
1137
|
+
await fs.writeFile(
|
|
1138
|
+
'.contextkit/config.yml',
|
|
1070
1139
|
`# ContextKit Configuration
|
|
1071
1140
|
_source:
|
|
1072
1141
|
tool: "@nolrm/contextkit"
|
|
@@ -1165,7 +1234,7 @@ https://www.npmjs.com/package/@nolrm/contextkit
|
|
|
1165
1234
|
status.features.pre_push_hook = hookChoices.prePush;
|
|
1166
1235
|
status.features.commit_msg_hook = hookChoices.commitMsg;
|
|
1167
1236
|
status.features.squad_ci_workflow = squadCi;
|
|
1168
|
-
|
|
1237
|
+
|
|
1169
1238
|
await this.statusManager.saveStatus(status);
|
|
1170
1239
|
console.log(chalk.green('✅ Status tracking initialized'));
|
|
1171
1240
|
} catch (error) {
|
|
@@ -1175,7 +1244,7 @@ https://www.npmjs.com/package/@nolrm/contextkit
|
|
|
1175
1244
|
|
|
1176
1245
|
async createProductContext() {
|
|
1177
1246
|
console.log(chalk.blue('📦 Creating product context files...'));
|
|
1178
|
-
|
|
1247
|
+
|
|
1179
1248
|
const missionContent = `# Product Mission
|
|
1180
1249
|
|
|
1181
1250
|
<!-- Content will be generated by running: ck analyze or manually fill this in -->
|
|
@@ -1373,13 +1442,13 @@ Unlike [COMPETITOR_OR_ALTERNATIVE], we provide [SPECIFIC_ADVANTAGE]. This result
|
|
|
1373
1442
|
await fs.writeFile('.contextkit/product/roadmap.md', roadmapContent);
|
|
1374
1443
|
await fs.writeFile('.contextkit/product/decisions.md', decisionsContent);
|
|
1375
1444
|
await fs.writeFile('.contextkit/product/context.md', contextContent);
|
|
1376
|
-
|
|
1445
|
+
|
|
1377
1446
|
console.log(chalk.green('✅ Product context files created'));
|
|
1378
1447
|
}
|
|
1379
1448
|
|
|
1380
1449
|
async createCorrectionsLog() {
|
|
1381
1450
|
console.log(chalk.blue('📝 Creating corrections log system...'));
|
|
1382
|
-
|
|
1451
|
+
|
|
1383
1452
|
const correctionsContent = `# ContextKit Corrections Log
|
|
1384
1453
|
|
|
1385
1454
|
## Description
|
|
@@ -1565,14 +1634,17 @@ Automatically track and log ContextKit performance issues during development ses
|
|
|
1565
1634
|
`;
|
|
1566
1635
|
|
|
1567
1636
|
await fs.writeFile('.contextkit/corrections.md', correctionsContent);
|
|
1568
|
-
await fs.writeFile(
|
|
1569
|
-
|
|
1637
|
+
await fs.writeFile(
|
|
1638
|
+
'.contextkit/instructions/core/auto-corrections-log.md',
|
|
1639
|
+
autoCorrectionsContent
|
|
1640
|
+
);
|
|
1641
|
+
|
|
1570
1642
|
console.log(chalk.green('✅ Corrections log system created'));
|
|
1571
1643
|
}
|
|
1572
1644
|
|
|
1573
1645
|
async createMetaInstructions() {
|
|
1574
1646
|
console.log(chalk.blue('📋 Creating meta instructions...'));
|
|
1575
|
-
|
|
1647
|
+
|
|
1576
1648
|
const preFlightContent = `---
|
|
1577
1649
|
description: Common Pre-Flight Steps for ContextKit Instructions
|
|
1578
1650
|
globs:
|
|
@@ -1646,13 +1718,13 @@ After completing any development session, automatically update the corrections l
|
|
|
1646
1718
|
|
|
1647
1719
|
await fs.writeFile('.contextkit/instructions/meta/pre-flight.md', preFlightContent);
|
|
1648
1720
|
await fs.writeFile('.contextkit/instructions/meta/post-flight.md', postFlightContent);
|
|
1649
|
-
|
|
1721
|
+
|
|
1650
1722
|
console.log(chalk.green('✅ Meta instructions created'));
|
|
1651
1723
|
}
|
|
1652
1724
|
|
|
1653
1725
|
async createPolicyFile() {
|
|
1654
1726
|
console.log(chalk.blue('⚖️ Creating policy file...'));
|
|
1655
|
-
|
|
1727
|
+
|
|
1656
1728
|
const policyContent = `# ContextKit Policy Configuration
|
|
1657
1729
|
|
|
1658
1730
|
## Enforcement Levels
|
|
@@ -1676,11 +1748,11 @@ enforcement:
|
|
|
1676
1748
|
`;
|
|
1677
1749
|
|
|
1678
1750
|
await fs.writeFile('.contextkit/policies/policy.yml', policyContent);
|
|
1679
|
-
|
|
1751
|
+
|
|
1680
1752
|
console.log(chalk.green('✅ Policy file created'));
|
|
1681
1753
|
}
|
|
1682
1754
|
|
|
1683
|
-
showSuccessMessage(hookChoices, platform = null,
|
|
1755
|
+
showSuccessMessage(hookChoices, platform = null, _projectType = '', _packageManager = '') {
|
|
1684
1756
|
console.log('');
|
|
1685
1757
|
console.log(chalk.green('🎉 ContextKit v1.0.0 successfully installed!'));
|
|
1686
1758
|
console.log('');
|
|
@@ -1702,7 +1774,9 @@ enforcement:
|
|
|
1702
1774
|
console.log(chalk.bold('📖 Quick Reference'));
|
|
1703
1775
|
console.log(''.padEnd(48, '─'));
|
|
1704
1776
|
console.log(`ck status → Check installation & integrations`);
|
|
1705
|
-
console.log(
|
|
1777
|
+
console.log(
|
|
1778
|
+
`ck <platform> → Add platform (claude, cursor, copilot, codex, opencode, gemini, aider, continue, windsurf)`
|
|
1779
|
+
);
|
|
1706
1780
|
console.log('');
|
|
1707
1781
|
console.log(`Docs → ${chalk.blue('https://contextkit-docs.vercel.app')}`);
|
|
1708
1782
|
console.log(`Issues → ${chalk.blue('https://github.com/nolrm/contextkit/issues')}`);
|
|
@@ -1715,7 +1789,7 @@ enforcement:
|
|
|
1715
1789
|
|
|
1716
1790
|
if (platform === 'cursor') {
|
|
1717
1791
|
console.log(chalk.bold('In Cursor Chat:'));
|
|
1718
|
-
console.log(` @.contextkit/commands/analyze.md`);
|
|
1792
|
+
console.log(` @.contextkit/commands/dev/analyze.md`);
|
|
1719
1793
|
console.log('');
|
|
1720
1794
|
console.log('Or via CLI:');
|
|
1721
1795
|
console.log(chalk.yellow('👉'), `/analyze`);
|
|
@@ -1741,19 +1815,23 @@ enforcement:
|
|
|
1741
1815
|
|
|
1742
1816
|
if (platform === 'cursor') {
|
|
1743
1817
|
console.log(chalk.bold('In Cursor Chat'));
|
|
1744
|
-
console.log(`@.contextkit/commands/create-component.md`);
|
|
1818
|
+
console.log(`@.contextkit/commands/dev/create-component.md`);
|
|
1745
1819
|
console.log(chalk.dim('"Create a Button component for customer checkout"'));
|
|
1746
1820
|
console.log('');
|
|
1747
1821
|
}
|
|
1748
1822
|
|
|
1749
1823
|
console.log(chalk.bold('In CLI'));
|
|
1750
|
-
console.log(
|
|
1824
|
+
console.log(
|
|
1825
|
+
chalk.dim(
|
|
1826
|
+
"Use your AI tool's slash command, e.g. /analyze or @.contextkit/commands/dev/create-component.md"
|
|
1827
|
+
)
|
|
1828
|
+
);
|
|
1751
1829
|
console.log('');
|
|
1752
1830
|
|
|
1753
1831
|
if (platform === 'claude' || platform === 'gemini') {
|
|
1754
1832
|
const toolName = platform === 'claude' ? 'Claude' : 'Gemini';
|
|
1755
1833
|
console.log(chalk.bold(`In ${toolName} CLI`));
|
|
1756
|
-
console.log(`read .contextkit/commands/analyze.md and execute`);
|
|
1834
|
+
console.log(`read .contextkit/commands/dev/analyze.md and execute`);
|
|
1757
1835
|
console.log('');
|
|
1758
1836
|
}
|
|
1759
1837
|
|
|
@@ -1761,6 +1839,179 @@ enforcement:
|
|
|
1761
1839
|
console.log('');
|
|
1762
1840
|
}
|
|
1763
1841
|
|
|
1842
|
+
async promptQualityTooling(packageManager, _options = {}) {
|
|
1843
|
+
// Only relevant for Node.js projects
|
|
1844
|
+
if (!(await fs.pathExists('package.json'))) return;
|
|
1845
|
+
|
|
1846
|
+
// Skip in CI / non-interactive mode
|
|
1847
|
+
if (process.env.CI === 'true' || process.env.NON_INTERACTIVE === 'true') return;
|
|
1848
|
+
|
|
1849
|
+
const pkg = await fs.readJson('package.json').catch(() => null);
|
|
1850
|
+
if (!pkg) return;
|
|
1851
|
+
|
|
1852
|
+
const hasFormat = !!(pkg.scripts && pkg.scripts.format);
|
|
1853
|
+
const hasLint = !!(pkg.scripts && pkg.scripts.lint);
|
|
1854
|
+
|
|
1855
|
+
// Both already present — nothing to do
|
|
1856
|
+
if (hasFormat && hasLint) return;
|
|
1857
|
+
|
|
1858
|
+
console.log('');
|
|
1859
|
+
console.log('──────────────────────────────────────────────');
|
|
1860
|
+
console.log(chalk.blue('🛠️ Format + Lint Quality Gates'));
|
|
1861
|
+
console.log('──────────────────────────────────────────────');
|
|
1862
|
+
console.log(chalk.dim('The pre-push hook runs format and lint scripts automatically'));
|
|
1863
|
+
console.log(chalk.dim('when present. Your project has none — add a minimal setup now?'));
|
|
1864
|
+
console.log('');
|
|
1865
|
+
|
|
1866
|
+
const { scaffold } = await inquirer.prompt([
|
|
1867
|
+
{
|
|
1868
|
+
type: 'confirm',
|
|
1869
|
+
name: 'scaffold',
|
|
1870
|
+
message: 'Add prettier + eslint setup? (adds scripts + config files)',
|
|
1871
|
+
default: false,
|
|
1872
|
+
},
|
|
1873
|
+
]);
|
|
1874
|
+
|
|
1875
|
+
if (scaffold) {
|
|
1876
|
+
await this.scaffoldQualityTooling(pkg, packageManager);
|
|
1877
|
+
} else {
|
|
1878
|
+
console.log(chalk.dim('💡 Add format/lint scripts later to activate these quality gates'));
|
|
1879
|
+
}
|
|
1880
|
+
console.log('');
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
async scaffoldQualityTooling(pkg, packageManager) {
|
|
1884
|
+
const pmInstallFlags = {
|
|
1885
|
+
npm: 'install --save-dev',
|
|
1886
|
+
yarn: 'add --dev',
|
|
1887
|
+
pnpm: 'add -D',
|
|
1888
|
+
bun: 'add -d',
|
|
1889
|
+
};
|
|
1890
|
+
const installFlag = pmInstallFlags[packageManager] || 'install --save-dev';
|
|
1891
|
+
const pm = packageManager === 'none' ? 'npm' : packageManager;
|
|
1892
|
+
|
|
1893
|
+
try {
|
|
1894
|
+
const created = [];
|
|
1895
|
+
|
|
1896
|
+
// 1. Add missing scripts to package.json
|
|
1897
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
1898
|
+
if (!pkg.scripts.format) {
|
|
1899
|
+
pkg.scripts.format = 'prettier --write .';
|
|
1900
|
+
created.push('format script');
|
|
1901
|
+
}
|
|
1902
|
+
if (!pkg.scripts.lint) {
|
|
1903
|
+
pkg.scripts.lint = 'eslint .';
|
|
1904
|
+
created.push('lint script');
|
|
1905
|
+
}
|
|
1906
|
+
await fs.writeFile('package.json', JSON.stringify(pkg, null, 2) + '\n');
|
|
1907
|
+
|
|
1908
|
+
// 2. Create .prettierrc if no existing config
|
|
1909
|
+
if (!(await this._hasExistingPrettierConfig(pkg))) {
|
|
1910
|
+
await fs.writeFile(
|
|
1911
|
+
'.prettierrc',
|
|
1912
|
+
JSON.stringify(
|
|
1913
|
+
{ singleQuote: true, semi: true, tabWidth: 2, printWidth: 100, trailingComma: 'es5' },
|
|
1914
|
+
null,
|
|
1915
|
+
2
|
|
1916
|
+
) + '\n'
|
|
1917
|
+
);
|
|
1918
|
+
created.push('.prettierrc');
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
// 3. Create .prettierignore if absent
|
|
1922
|
+
if (!(await fs.pathExists('.prettierignore'))) {
|
|
1923
|
+
await fs.writeFile('.prettierignore', 'node_modules/\ncoverage/\ndist/\nbuild/\n');
|
|
1924
|
+
created.push('.prettierignore');
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
// 4. Create eslint.config.js if no existing config
|
|
1928
|
+
if (!(await this._hasExistingEslintConfig(pkg))) {
|
|
1929
|
+
await fs.writeFile(
|
|
1930
|
+
'eslint.config.js',
|
|
1931
|
+
`const js = require('@eslint/js');
|
|
1932
|
+
const globals = require('globals');
|
|
1933
|
+
|
|
1934
|
+
module.exports = [
|
|
1935
|
+
js.configs.recommended,
|
|
1936
|
+
{
|
|
1937
|
+
languageOptions: {
|
|
1938
|
+
ecmaVersion: 2022,
|
|
1939
|
+
globals: {
|
|
1940
|
+
...globals.node,
|
|
1941
|
+
},
|
|
1942
|
+
},
|
|
1943
|
+
rules: {
|
|
1944
|
+
'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
|
|
1945
|
+
},
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
files: ['**/__tests__/**/*.js', '**/*.test.js'],
|
|
1949
|
+
languageOptions: {
|
|
1950
|
+
globals: {
|
|
1951
|
+
...globals.jest,
|
|
1952
|
+
},
|
|
1953
|
+
},
|
|
1954
|
+
},
|
|
1955
|
+
];\n`
|
|
1956
|
+
);
|
|
1957
|
+
created.push('eslint.config.js');
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
// 5. Install devDependencies
|
|
1961
|
+
console.log(chalk.blue(`\n📦 Installing prettier + eslint...`));
|
|
1962
|
+
childProcess.execSync(`${pm} ${installFlag} prettier eslint @eslint/js globals`, {
|
|
1963
|
+
stdio: 'inherit',
|
|
1964
|
+
});
|
|
1965
|
+
|
|
1966
|
+
console.log('');
|
|
1967
|
+
console.log(chalk.green('✅ Quality tooling ready:'));
|
|
1968
|
+
created.forEach((item) => console.log(chalk.dim(` • ${item}`)));
|
|
1969
|
+
console.log(chalk.dim(' Run npm run format to apply formatting to existing files'));
|
|
1970
|
+
} catch (error) {
|
|
1971
|
+
console.log(chalk.yellow('⚠️ Could not complete quality tooling setup:'), error.message);
|
|
1972
|
+
console.log(chalk.dim(' You can set this up manually later'));
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
async _hasExistingPrettierConfig(pkg) {
|
|
1977
|
+
if (pkg.prettier) return true;
|
|
1978
|
+
const configs = [
|
|
1979
|
+
'.prettierrc',
|
|
1980
|
+
'.prettierrc.json',
|
|
1981
|
+
'.prettierrc.js',
|
|
1982
|
+
'.prettierrc.mjs',
|
|
1983
|
+
'.prettierrc.cjs',
|
|
1984
|
+
'.prettierrc.yaml',
|
|
1985
|
+
'.prettierrc.yml',
|
|
1986
|
+
'.prettierrc.toml',
|
|
1987
|
+
'prettier.config.js',
|
|
1988
|
+
'prettier.config.mjs',
|
|
1989
|
+
'prettier.config.cjs',
|
|
1990
|
+
];
|
|
1991
|
+
for (const f of configs) {
|
|
1992
|
+
if (await fs.pathExists(f)) return true;
|
|
1993
|
+
}
|
|
1994
|
+
return false;
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
async _hasExistingEslintConfig(pkg) {
|
|
1998
|
+
if (pkg.eslintConfig) return true;
|
|
1999
|
+
const configs = [
|
|
2000
|
+
'eslint.config.js',
|
|
2001
|
+
'eslint.config.mjs',
|
|
2002
|
+
'eslint.config.cjs',
|
|
2003
|
+
'.eslintrc',
|
|
2004
|
+
'.eslintrc.js',
|
|
2005
|
+
'.eslintrc.json',
|
|
2006
|
+
'.eslintrc.yml',
|
|
2007
|
+
'.eslintrc.yaml',
|
|
2008
|
+
];
|
|
2009
|
+
for (const f of configs) {
|
|
2010
|
+
if (await fs.pathExists(f)) return true;
|
|
2011
|
+
}
|
|
2012
|
+
return false;
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1764
2015
|
async _findFileUpward(name, maxLevels) {
|
|
1765
2016
|
let dir = process.cwd();
|
|
1766
2017
|
for (let i = 0; i <= maxLevels; i++) {
|
|
@@ -1771,6 +2022,59 @@ enforcement:
|
|
|
1771
2022
|
}
|
|
1772
2023
|
return false;
|
|
1773
2024
|
}
|
|
2025
|
+
|
|
2026
|
+
async createQualityGatesConfig() {
|
|
2027
|
+
const configPath = '.contextkit/quality-gates.yml';
|
|
2028
|
+
if (await fs.pathExists(configPath)) return;
|
|
2029
|
+
const content = `# Quality Gates Configuration
|
|
2030
|
+
# Disable specific gates by uncommenting keys below.
|
|
2031
|
+
# All gates are enabled by default.
|
|
2032
|
+
# Reference: https://contextkit-docs.vercel.app/docs/quality-gates
|
|
2033
|
+
|
|
2034
|
+
disabled:
|
|
2035
|
+
# Node.js gates
|
|
2036
|
+
# - typescript # skip TypeScript type checking
|
|
2037
|
+
# - eslint # skip ESLint (direct, not via script)
|
|
2038
|
+
# - prettier # skip Prettier (direct, not via script)
|
|
2039
|
+
# - format # skip npm run format
|
|
2040
|
+
# - lint # skip npm run lint
|
|
2041
|
+
# - build # skip npm run build
|
|
2042
|
+
# - test # skip npm test
|
|
2043
|
+
# - e2e # skip npm run e2e
|
|
2044
|
+
# Python gates
|
|
2045
|
+
# - ruff-lint # skip ruff/flake8 lint
|
|
2046
|
+
# - typecheck # skip mypy
|
|
2047
|
+
# - ruff-format # skip ruff/black format check
|
|
2048
|
+
# - pytest # skip pytest
|
|
2049
|
+
# Rust gates
|
|
2050
|
+
# - cargo-check # skip cargo check
|
|
2051
|
+
# - clippy # skip cargo clippy
|
|
2052
|
+
# - cargo-test # skip cargo test
|
|
2053
|
+
# Go gates
|
|
2054
|
+
# - go-vet # skip go vet
|
|
2055
|
+
# - golangci-lint # skip golangci-lint
|
|
2056
|
+
# - go-test # skip go test
|
|
2057
|
+
# PHP gates
|
|
2058
|
+
# - phpstan # skip PHPStan
|
|
2059
|
+
# - phpunit # skip PHPUnit
|
|
2060
|
+
# Ruby gates
|
|
2061
|
+
# - rubocop # skip RuboCop
|
|
2062
|
+
# - rspec # skip RSpec / rake test
|
|
2063
|
+
# Java / Kotlin gates
|
|
2064
|
+
# - maven-verify # skip mvn verify
|
|
2065
|
+
# - gradle-check # skip gradle check
|
|
2066
|
+
# - ktlint # skip ktlint
|
|
2067
|
+
# - kotlin-test # skip gradle test
|
|
2068
|
+
# Swift gates
|
|
2069
|
+
# - swiftlint # skip SwiftLint
|
|
2070
|
+
# - swift-test # skip swift test
|
|
2071
|
+
# .NET gates
|
|
2072
|
+
# - dotnet-build # skip dotnet build
|
|
2073
|
+
# - dotnet-test # skip dotnet test
|
|
2074
|
+
`;
|
|
2075
|
+
await fs.writeFile(configPath, content);
|
|
2076
|
+
console.log(chalk.green('✅ Created .contextkit/quality-gates.yml'));
|
|
2077
|
+
}
|
|
1774
2078
|
}
|
|
1775
2079
|
|
|
1776
2080
|
async function install(options) {
|
|
@@ -1779,3 +2083,4 @@ async function install(options) {
|
|
|
1779
2083
|
}
|
|
1780
2084
|
|
|
1781
2085
|
module.exports = install;
|
|
2086
|
+
module.exports.InstallCommand = InstallCommand;
|