diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 07a9989..d121970 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -39,3 +39,4 @@ The following instructions are only to be applied when performing a code review. * [ ] The file name is lower case, with words separated by hyphens. * [ ] Encourage the use of `tools`, but it's not required. * [ ] Strongly encourage the use of `model` to specify the model that the chat mode is optimised for. + diff --git a/CONFIG.md b/CONFIG.md index 5819478..cd8e5e6 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -183,6 +183,64 @@ The `node awesome-copilot.js init` command automatically configures VS Code to d No manual VS Code configuration needed! +## GitHub Copilot Repository Instructions + +Awesome Copilot can generate a `.github/copilot-instructions.md` file that provides repository-level instructions to GitHub Copilot. This feature supports GitHub's native repository instructions capability, which automatically applies instructions to all Copilot interactions within your repository. + +### Generating Repository Instructions + +```bash +# Generate basic repository instructions file +node /path/to/awesome-copilot/awesome-copilot.js generate-repo-instructions + +# Generate with full instruction content included +node /path/to/awesome-copilot/awesome-copilot.js generate-repo-instructions --consolidated + +# Custom output location +node /path/to/awesome-copilot/awesome-copilot.js generate-repo-instructions --output=.copilot/instructions.md + +# Generate without header +node /path/to/awesome-copilot/awesome-copilot.js generate-repo-instructions --no-header +``` + +### Template Options + +- **`repository` (default)**: Lists enabled instructions with references to individual files +- **`consolidated`**: Includes full content from all enabled instruction files +- **`basic`**: Simple list without detailed formatting + +### Benefits of Repository Instructions + +- **Automatic Application**: Instructions apply to all team members without manual configuration +- **Version Control**: Instructions are tracked with your code and evolve with your project +- **IDE Agnostic**: Works across VS Code, Visual Studio, GitHub Copilot CLI, and web interfaces +- **Consistency**: Ensures all team members get the same Copilot behavior +- **No Setup Required**: New team members automatically get proper instructions + +### Integration with Configuration + +The repository instructions are generated based on your enabled instructions in the configuration file: + +```yaml +instructions: + csharp: true # Included in repository instructions + python: true # Included in repository instructions + java: false # Excluded from repository instructions + +collections: + testing-automation: true # All instructions in this collection included +``` + +### Workflow Integration + +Repository instructions work seamlessly with the existing workflow: + +1. **Configure**: Enable instructions in your config file +2. **Apply**: Run `awesome-copilot apply` to copy files to your project +3. **Generate**: Run `generate-repo-instructions` to create the repository instructions file +4. **Commit**: Add the generated file to version control +5. **Collaborate**: Team members automatically get consistent Copilot behavior + ## Examples ### Frontend React Project diff --git a/README.md b/README.md index 25ea21b..84918ae 100644 --- a/README.md +++ b/README.md @@ -85,8 +85,33 @@ Use our configuration system to manage all customizations in one place: node /path/to/awesome-copilot/awesome-copilot.js apply ``` +6. **Generate repository instructions** (optional, for GitHub Copilot repository-level instructions): + ```bash + # Generate .github/copilot-instructions.md from enabled instructions + node /path/to/awesome-copilot/awesome-copilot.js generate-repo-instructions + + # Or generate with full instruction content included + node /path/to/awesome-copilot/awesome-copilot.js generate-repo-instructions --consolidated + ``` + See [CONFIG.md](CONFIG.md) for detailed configuration documentation. +#### ๐Ÿค– GitHub Copilot Repository Instructions + +Awesome Copilot can generate a `.github/copilot-instructions.md` file that provides repository-level instructions to GitHub Copilot. This file is automatically recognized by GitHub Copilot and applies to all code generation within your repository. + +**Benefits:** +- Instructions automatically apply to all Copilot interactions in your repository +- No need to manually configure VS Code settings for each team member +- Instructions are version-controlled with your code +- Works across all supported IDEs and GitHub Copilot interfaces + +**Templates:** +- `--basic`: Simple list of enabled instructions (default) +- `--consolidated`: Includes full content of all enabled instruction files +- Custom templates can be created by modifying the `repository-instructions.js` file + + #### โš–๏ธ Configuration Precedence Rules Awesome Copilot uses an **effective state system** that respects explicit overrides while allowing collections to provide convenient defaults. The effective state computation follows these precise rules: diff --git a/apply-config.js b/apply-config.js index 1e66ace..b1e5c65 100755 --- a/apply-config.js +++ b/apply-config.js @@ -196,6 +196,11 @@ async function applyConfig(configPath = "awesome-copilot.config.yml") { console.log("2. Use prompts with /awesome-copilot command in GitHub Copilot Chat"); console.log("3. Instructions will automatically apply to your coding"); console.log("4. Import chat modes in VS Code settings"); + + // Suggest generating repository instructions if instructions are enabled + if (summary.instructions > 0) { + console.log("5. Consider running 'awesome-copilot generate-repo-instructions' to create .github/copilot-instructions.md"); + } } /** diff --git a/awesome-copilot.js b/awesome-copilot.js index 61f185e..15580e7 100755 --- a/awesome-copilot.js +++ b/awesome-copilot.js @@ -68,6 +68,15 @@ const commands = { } }, + "generate-repo-instructions": { + description: "Generate .github/copilot-instructions.md from enabled instructions", + usage: "awesome-copilot generate-repo-instructions [config-file] [--consolidated|--basic] [--output=] [--no-header]", + action: async (args) => { + const { handleGenerateRepoInstructions } = require("./repository-instructions"); + await handleGenerateRepoInstructions(args); + } + }, + help: { description: "Show help information", usage: "awesome-copilot help", @@ -101,11 +110,14 @@ function showHelp() { console.log(" awesome-copilot toggle instructions all off --config team.yml # Disable all instructions"); console.log(" awesome-copilot toggle prompts all on --all # Force enable ALL prompts (override explicit settings)"); console.log(" awesome-copilot toggle collections testing-automation on --apply # Enable collection and apply"); + console.log(" awesome-copilot generate-repo-instructions # Generate .github/copilot-instructions.md"); + console.log(" awesome-copilot generate-repo-instructions --consolidated # Include full instruction content"); console.log(""); console.log("Workflow:"); console.log(" 1. Run 'awesome-copilot init' to create a configuration file"); console.log(" 2. Use 'awesome-copilot list' and 'awesome-copilot toggle' to manage enabled items"); console.log(" 3. Run 'awesome-copilot apply' to copy files to your project"); + console.log(" 4. Run 'awesome-copilot generate-repo-instructions' for GitHub Copilot repository instructions"); } function showError(message) { diff --git a/repository-instructions.js b/repository-instructions.js new file mode 100644 index 0000000..6087edd --- /dev/null +++ b/repository-instructions.js @@ -0,0 +1,344 @@ +#!/usr/bin/env node + +const fs = require("fs"); +const path = require("path"); +const { parseConfigYamlContent } = require("./apply-config"); +const { computeEffectiveItemStates } = require("./config-manager"); + +/** + * Generate or update .github/copilot-instructions.md based on enabled instructions + */ +async function generateRepositoryInstructions(configPath = "awesome-copilot.config.yml", options = {}) { + const { + outputFile = ".github/copilot-instructions.md", + template = "repository", + includeHeader = true, + rootDir = __dirname + } = options; + + console.log("๐Ÿค– Generating GitHub Copilot repository instructions..."); + + // Load configuration + if (!fs.existsSync(configPath)) { + throw new Error(`Configuration file not found: ${configPath}`); + } + + const rawContent = fs.readFileSync(configPath, "utf8"); + const config = parseConfigYamlContent(rawContent) || {}; + + // Compute effective states to determine which instructions are enabled + const effectiveStates = computeEffectiveItemStates(config); + + // Get enabled instructions + const enabledInstructions = []; + for (const [instructionName, state] of Object.entries(effectiveStates.instructions)) { + if (state.enabled) { + const instructionPath = path.join(rootDir, "instructions", `${instructionName}.instructions.md`); + if (fs.existsSync(instructionPath)) { + enabledInstructions.push({ + name: instructionName, + path: instructionPath, + reason: state.reason + }); + } + } + } + + console.log(`๐Ÿ“‹ Found ${enabledInstructions.length} enabled instructions`); + + // Generate the repository instructions content + const content = await generateInstructionsContent(enabledInstructions, template, includeHeader); + + // Ensure output directory exists + const outputDir = path.dirname(outputFile); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + console.log(`๐Ÿ“ Created directory: ${outputDir}`); + } + + // Write the file + fs.writeFileSync(outputFile, content); + console.log(`โœ… Generated repository instructions: ${outputFile}`); + + return { + file: outputFile, + instructionsCount: enabledInstructions.length, + instructions: enabledInstructions.map(i => i.name) + }; +} + +/** + * Generate the content for the repository instructions file + */ +async function generateInstructionsContent(enabledInstructions, template, includeHeader) { + let content = ""; + + if (includeHeader) { + content += generateHeader(); + } + + if (enabledInstructions.length === 0) { + content += generateEmptyInstructions(); + return content; + } + + // Add instructions based on template + if (template === "repository") { + content += generateRepositoryTemplate(enabledInstructions); + } else if (template === "consolidated") { + content += await generateConsolidatedTemplate(enabledInstructions); + } else { + content += await generateBasicTemplate(enabledInstructions); + } + + return content; +} + +/** + * Generate header for the repository instructions + */ +function generateHeader() { + return `# GitHub Copilot Repository Instructions + +This file contains custom instructions for GitHub Copilot when working in this repository. +These instructions are automatically generated from the enabled instruction files in the awesome-copilot configuration. + +## How This Works + +GitHub Copilot will automatically use these instructions when: +- You're working in this repository +- Copilot is generating code, explanations, or suggestions +- You're using Copilot Chat within this repository context + +## Instructions Source + +These instructions are compiled from the following sources: +- Enabled instruction files from the awesome-copilot configuration +- Repository-specific coding standards and best practices +- Technology-specific guidelines relevant to this project + +--- + +`; +} + +/** + * Generate content when no instructions are enabled + */ +function generateEmptyInstructions() { + return `## No Instructions Enabled + +Currently, no instruction files are enabled in the awesome-copilot configuration. + +To add instructions: +1. Edit your \`awesome-copilot.config.yml\` file +2. Enable the desired instruction files +3. Run \`awesome-copilot generate-repo-instructions\` to update this file + +Available instructions can be found in the \`instructions/\` directory. +`; +} + +/** + * Generate repository-style template with references to instruction files + */ +function generateRepositoryTemplate(enabledInstructions) { + let content = `## Active Instructions + +The following ${enabledInstructions.length} instruction set${enabledInstructions.length !== 1 ? 's are' : ' is'} currently active for this repository: + +`; + + // Group instructions by reason + const groupedByReason = {}; + enabledInstructions.forEach(instruction => { + const reason = instruction.reason || 'explicit'; + if (!groupedByReason[reason]) { + groupedByReason[reason] = []; + } + groupedByReason[reason].push(instruction); + }); + + // Add instructions grouped by reason + for (const [reason, instructions] of Object.entries(groupedByReason)) { + content += `### ${reason === 'explicit' ? 'Explicitly Enabled' : + reason === 'collection' ? 'Enabled via Collections' : + reason.charAt(0).toUpperCase() + reason.slice(1)}\n\n`; + + instructions.forEach(instruction => { + const title = extractTitleFromInstruction(instruction.path) || instruction.name; + content += `- **${title}** (\`${instruction.name}\`)\n`; + }); + content += '\n'; + } + + content += `## Instruction Details + +For detailed information about each instruction set, refer to the individual instruction files in the \`instructions/\` directory. + +`; + + return content; +} + +/** + * Generate consolidated template with full instruction content + */ +async function generateConsolidatedTemplate(enabledInstructions) { + let content = `## Consolidated Instructions + +The following instructions combine all enabled instruction sets: + +`; + + for (const instruction of enabledInstructions) { + const title = extractTitleFromInstruction(instruction.path) || instruction.name; + const instructionContent = fs.readFileSync(instruction.path, 'utf8'); + + // Extract the main content (skip frontmatter) + const cleanContent = extractInstructionContent(instructionContent); + + content += `### ${title} + +${cleanContent} + +--- + +`; + } + + return content; +} + +/** + * Generate basic template with simple list + */ +async function generateBasicTemplate(enabledInstructions) { + let content = `## Enabled Instructions + +`; + + enabledInstructions.forEach(instruction => { + const title = extractTitleFromInstruction(instruction.path) || instruction.name; + content += `- ${title}\n`; + }); + + content += `\nFor detailed instruction content, see the individual files in the \`instructions/\` directory. + +`; + + return content; +} + +/** + * Extract title from instruction file + */ +function extractTitleFromInstruction(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split('\n'); + + // Look for title in frontmatter first + let inFrontmatter = false; + for (const line of lines) { + if (line.trim() === '---') { + inFrontmatter = !inFrontmatter; + continue; + } + + if (inFrontmatter && line.includes('title:')) { + const title = line.substring(line.indexOf('title:') + 6).trim(); + return title.replace(/^['"]|['"]$/g, ''); + } + } + + // Look for first heading + for (const line of lines) { + if (line.startsWith('# ')) { + return line.substring(2).trim(); + } + } + + return null; + } catch (error) { + return null; + } +} + +/** + * Extract main content from instruction file (skip frontmatter) + */ +function extractInstructionContent(content) { + const lines = content.split('\n'); + let inFrontmatter = false; + let frontmatterEnded = false; + const contentLines = []; + + for (const line of lines) { + if (line.trim() === '---') { + if (!inFrontmatter) { + inFrontmatter = true; + continue; + } else if (inFrontmatter && !frontmatterEnded) { + frontmatterEnded = true; + continue; + } + } + + if (!inFrontmatter || frontmatterEnded) { + contentLines.push(line); + } + } + + return contentLines.join('\n').trim(); +} + +/** + * CLI handler for generate-repo-instructions command + */ +async function handleGenerateRepoInstructions(args) { + const configFile = args.find(arg => !arg.startsWith('--')) || "awesome-copilot.config.yml"; + + // Parse flags + const template = args.includes('--consolidated') ? 'consolidated' : + args.includes('--basic') ? 'basic' : 'repository'; + const outputFile = args.find(arg => arg.startsWith('--output='))?.split('=')[1] || + ".github/copilot-instructions.md"; + const noHeader = args.includes('--no-header'); + + try { + const result = await generateRepositoryInstructions(configFile, { + outputFile, + template, + includeHeader: !noHeader + }); + + console.log(`\n๐Ÿ“‹ Repository instructions generated successfully!`); + console.log(`๐Ÿ“ File: ${result.file}`); + console.log(`๐Ÿ“Š Instructions: ${result.instructionsCount}`); + + if (result.instructions.length > 0) { + console.log(`๐Ÿ“ Included: ${result.instructions.join(', ')}`); + } + + console.log(`\n๐Ÿ’ก Next steps:`); + console.log(` โ€ข Commit the generated file to enable repository-wide Copilot instructions`); + console.log(` โ€ข GitHub Copilot will automatically use these instructions in this repository`); + console.log(` โ€ข Update instructions by modifying your config and re-running this command`); + + } catch (error) { + console.error(`โŒ Error generating repository instructions: ${error.message}`); + process.exit(1); + } +} + +module.exports = { + generateRepositoryInstructions, + handleGenerateRepoInstructions +}; + +// CLI usage +if (require.main === module) { + const args = process.argv.slice(2); + handleGenerateRepoInstructions(args); +} \ No newline at end of file diff --git a/test-all.js b/test-all.js index 55eac5f..8c4ead0 100644 --- a/test-all.js +++ b/test-all.js @@ -11,7 +11,7 @@ const { runTests: runApplyTests } = require('./test-apply-effective'); async function runAllTests() { console.log('๐Ÿงช Running Awesome Copilot Comprehensive Test Suite\n'); - console.log('=' * 60); + console.log('='.repeat(60)); const results = { unit: false, @@ -22,7 +22,7 @@ async function runAllTests() { try { console.log('\n๐Ÿ“Š Unit Tests (Effective State Computation)'); - console.log('-' * 45); + console.log('-'.repeat(45)); results.unit = await runUnitTests(); } catch (error) { console.error('Unit tests failed with error:', error.message); @@ -30,7 +30,7 @@ async function runAllTests() { try { console.log('\n๐Ÿ”„ Integration Tests (Toggle+Apply Idempotency)'); - console.log('-' * 48); + console.log('-'.repeat(48)); results.integration = await runIntegrationTests(); } catch (error) { console.error('Integration tests failed with error:', error.message); @@ -38,7 +38,7 @@ async function runAllTests() { try { console.log('\nโŒจ๏ธ CLI Tests (List and Toggle Commands)'); - console.log('-' * 40); + console.log('-'.repeat(40)); results.cli = await runCliTests(); } catch (error) { console.error('CLI tests failed with error:', error.message); @@ -46,22 +46,32 @@ async function runAllTests() { try { console.log('\n๐ŸŽฏ Apply Tests (Effective States in Apply)'); - console.log('-' * 42); + console.log('-'.repeat(42)); results.apply = await runApplyTests(); } catch (error) { console.error('Apply tests failed with error:', error.message); } + try { + console.log('\n๐Ÿค– Repository Instructions Tests'); + console.log('-'.repeat(33)); + const { runTests: runRepoInstructionsTests } = require('./test-repository-instructions'); + results.repoInstructions = await runRepoInstructionsTests(); + } catch (error) { + console.error('Repository instructions tests failed with error:', error.message); + } + // Summary - console.log('\n' + '=' * 60); + console.log('\n' + '='.repeat(60)); console.log('๐Ÿ“‹ Test Suite Summary'); - console.log('=' * 60); + console.log('='.repeat(60)); const testTypes = [ { name: 'Unit Tests', result: results.unit, emoji: '๐Ÿ“Š' }, { name: 'Integration Tests', result: results.integration, emoji: '๐Ÿ”„' }, { name: 'CLI Tests', result: results.cli, emoji: 'โŒจ๏ธ' }, - { name: 'Apply Tests', result: results.apply, emoji: '๐ŸŽฏ' } + { name: 'Apply Tests', result: results.apply, emoji: '๐ŸŽฏ' }, + { name: 'Repo Instructions', result: results.repoInstructions, emoji: '๐Ÿค–' } ]; testTypes.forEach(test => { @@ -72,7 +82,7 @@ async function runAllTests() { const passedCount = Object.values(results).filter(Boolean).length; const totalCount = Object.keys(results).length; - console.log('\n' + '-' * 60); + console.log('\n' + '-'.repeat(60)); console.log(`Overall Result: ${passedCount}/${totalCount} test suites passed`); if (passedCount === totalCount) { diff --git a/test-integration.yml b/test-integration.yml new file mode 100644 index 0000000..b836334 --- /dev/null +++ b/test-integration.yml @@ -0,0 +1,34 @@ +# Awesome Copilot Configuration File +# Generated on 2025-09-23T23:16:09.548Z +# +# This file uses effective state precedence: +# 1. Explicit item settings (true/false) override everything +# 2. Items not listed inherit from enabled collections +# 3. Otherwise items are disabled +# +# To use: +# - Enable collections for curated sets of related items +# - Explicitly set individual items to true/false to override collections +# - Items not mentioned will follow collection settings +# +# After configuring, run: awesome-copilot apply +# + +version: "1.0" +project: + name: "My Project" + description: "A project using awesome-copilot customizations" + output_directory: ".github" +prompts: +instructions: +chatmodes: +collections: + azure-cloud-development: false + csharp-dotnet-development: false + database-data-management: false + devops-oncall: false + frontend-web-dev: false + project-planning: false + security-best-practices: false + technical-spike: false + testing-automation: false diff --git a/test-repository-instructions.js b/test-repository-instructions.js new file mode 100644 index 0000000..0598fb6 --- /dev/null +++ b/test-repository-instructions.js @@ -0,0 +1,198 @@ +#!/usr/bin/env node + +const fs = require("fs"); +const path = require("path"); +const { generateRepositoryInstructions } = require("./repository-instructions"); + +console.log("๐Ÿงช Testing Repository Instructions Generation"); +console.log("=".repeat(50)); + +/** + * Test repository instructions generation + */ +async function testRepositoryInstructions() { + const testConfigPath = "test-repo-instructions.yml"; + const testOutputPath = ".github/test-copilot-instructions.md"; + + // Create a test configuration with some enabled instructions + const testConfig = `# Test configuration for repository instructions +instructions: + javascript: true + python: false + csharp: true + +collections: + frontend-web-dev: true +`; + + try { + // Write test config + fs.writeFileSync(testConfigPath, testConfig); + console.log("โœ… Created test configuration"); + + // Test basic generation + console.log("\n๐Ÿ“‹ Testing basic repository instructions generation..."); + const result = await generateRepositoryInstructions(testConfigPath, { + outputFile: testOutputPath, + template: "repository" + }); + + console.log(`โœ… Generated file: ${result.file}`); + console.log(`๐Ÿ“Š Instructions count: ${result.instructionsCount}`); + console.log(`๐Ÿ“ Instructions: ${result.instructions.join(', ')}`); + + // Verify the file was created + if (fs.existsSync(testOutputPath)) { + const content = fs.readFileSync(testOutputPath, 'utf8'); + console.log(`๐Ÿ“„ File size: ${content.length} characters`); + + // Check for expected content + const hasHeader = content.includes("GitHub Copilot Repository Instructions"); + const hasInstructions = content.includes("Active Instructions"); + + console.log(`โœ… Has header: ${hasHeader}`); + console.log(`โœ… Has instructions section: ${hasInstructions}`); + + if (hasHeader && hasInstructions) { + console.log("โœ… Content validation passed"); + } else { + console.log("โŒ Content validation failed"); + return false; + } + } else { + console.log("โŒ Output file was not created"); + return false; + } + + // Test consolidated template + console.log("\n๐Ÿ“‹ Testing consolidated template..."); + const consolidatedPath = ".github/test-consolidated-instructions.md"; + await generateRepositoryInstructions(testConfigPath, { + outputFile: consolidatedPath, + template: "consolidated" + }); + + if (fs.existsSync(consolidatedPath)) { + const consolidatedContent = fs.readFileSync(consolidatedPath, 'utf8'); + console.log(`โœ… Consolidated file created (${consolidatedContent.length} characters)`); + fs.unlinkSync(consolidatedPath); + } + + // Test empty config + console.log("\n๐Ÿ“‹ Testing empty configuration..."); + const emptyConfig = `# Empty configuration +instructions: {} +`; + const emptyConfigPath = "test-empty-repo-instructions.yml"; + const emptyOutputPath = ".github/test-empty-instructions.md"; + + fs.writeFileSync(emptyConfigPath, emptyConfig); + + await generateRepositoryInstructions(emptyConfigPath, { + outputFile: emptyOutputPath, + template: "repository" + }); + + if (fs.existsSync(emptyOutputPath)) { + const emptyContent = fs.readFileSync(emptyOutputPath, 'utf8'); + const hasEmptyMessage = emptyContent.includes("No Instructions Enabled"); + console.log(`โœ… Empty config handled correctly: ${hasEmptyMessage}`); + fs.unlinkSync(emptyOutputPath); + } + + // Cleanup + fs.unlinkSync(testConfigPath); + fs.unlinkSync(emptyConfigPath); + fs.unlinkSync(testOutputPath); + + console.log("\n๐ŸŽ‰ All repository instructions tests passed!"); + return true; + + } catch (error) { + console.error(`โŒ Test failed: ${error.message}`); + + // Cleanup on error + [testConfigPath, testOutputPath, "test-empty-repo-instructions.yml", ".github/test-empty-instructions.md", ".github/test-consolidated-instructions.md"].forEach(file => { + if (fs.existsSync(file)) { + fs.unlinkSync(file); + } + }); + + return false; + } +} + +/** + * Test CLI integration + */ +async function testCLIIntegration() { + console.log("\n๐Ÿ–ฅ๏ธ Testing CLI Integration"); + console.log("-".repeat(30)); + + try { + // Test the awesome-copilot command includes the new command + const { main } = require("./awesome-copilot"); + + // Check if the command is registered + const originalArgv = process.argv; + process.argv = ["node", "awesome-copilot.js", "help"]; + + // Capture help output + const originalLog = console.log; + let helpOutput = ""; + console.log = (...args) => { + helpOutput += args.join(" ") + "\n"; + }; + + try { + main(); + } catch (error) { + // Expected for help command + } + + console.log = originalLog; + process.argv = originalArgv; + + // Check if our command is in the help output + const hasRepoInstructionsCommand = helpOutput.includes("generate-repo-instructions"); + console.log(`โœ… Command registered in CLI: ${hasRepoInstructionsCommand}`); + + return hasRepoInstructionsCommand; + + } catch (error) { + console.error(`โŒ CLI integration test failed: ${error.message}`); + return false; + } +} + +/** + * Main test runner + */ +async function runTests() { + const test1 = await testRepositoryInstructions(); + const test2 = await testCLIIntegration(); + + console.log("\n" + "=".repeat(50)); + console.log("๐Ÿ“Š Test Results Summary"); + console.log("=".repeat(50)); + console.log(`Repository Instructions Generation: ${test1 ? "โœ… PASS" : "โŒ FAIL"}`); + console.log(`CLI Integration: ${test2 ? "โœ… PASS" : "โŒ FAIL"}`); + + const allPassed = test1 && test2; + console.log(`\nOverall Result: ${allPassed ? "โœ… ALL TESTS PASSED" : "โŒ SOME TESTS FAILED"}`); + + if (allPassed) { + console.log("\n๐ŸŽ‰ Repository instructions feature is working correctly!"); + } + + return allPassed; +} + +// Run tests +if (require.main === module) { + runTests().then(success => { + process.exit(success ? 0 : 1); + }); +} + +module.exports = { runTests }; \ No newline at end of file