Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 31, 2026

Implementation Plan: GitHub Copilot SDK Integration and Multi-Convention Support

Phase 1: Core Infrastructure

  • Create source/utils/commit-conventions.js with 4 conventions (clean, conventional, gitmoji, simple)
  • Add convention management functions to source/utils/config-manager.js

Phase 2: AI Provider Integration

  • Update source/providers/ai-provider.js with real Copilot SDK integration
  • Implement proper error handling and OpenAI fallback
  • Support convention selection in generateCommitMessage

Phase 3: Authentication Updates

  • Update source/commands/auth.js to check for GitHub CLI
  • Add gh CLI status verification

Phase 4: UI Enhancements

  • Add promptConventionSelection() to source/utils/ui.js
  • Update confirmCommit() to support convention switching
  • Display convention name in UI

Phase 5: Command Updates

  • Update source/commands/commit.js with regeneration support
  • Add convention parameter to processFile and processFilesInteractively
  • Implement regeneration loop with max attempts

Phase 6: CLI Interface

  • Add --convention flag to commit command in source/cli.js
  • Add config set-convention subcommand
  • Update config display to show convention

Phase 7: Testing & Validation

  • Update tests for new convention system
  • Run linter and tests (all passing)
  • Address PR review feedback (Round 1)
  • Remove dead code for GitHub token storage
  • Add max attempts to processFilesInteractively
  • Improve Copilot SDK cleanup with finally block
  • Use dynamic convention validation
  • Enhance response parsing for Copilot SDK
  • Address PR review feedback (Round 2)
  • Fix invalid model name (gpt-4.1 → gpt-4o)
  • Fix attempts increment in processFilesInteractively
  • Add documentation for response shape handling
  • Improve error messages with diagnostic info
  • Handle invalid conventions in config display
  • Add authenticatedAt timestamp for Copilot auth
  • Clarify validation comment accuracy
  • Add validation to setConvention for all code paths
  • Improve warning message readability
Original prompt

Implement GitHub Copilot SDK Integration and Multi-Convention Support

Objective

Complete the GitHub Copilot SDK integration in PR #40 and add support for multiple commit message conventions with Clean Commit as the default.

Base Branch

This PR should target the copilot/migrate-to-commander-and-copilot branch from PR #40.

Requirements

1. Create Commit Convention System

Create new file: source/utils/commit-conventions.js

export const CONVENTIONS = {
  clean: {
    name: 'Clean Commit',
    description: 'wgtechlabs Clean Commit format with emojis',
    buildPrompt: (diff, filePath) => `You are an expert at writing git commit messages following the "Clean Commit" format.

**Clean Commit Format:**
<emoji> <type>: <description>
<emoji> <type> (<scope>): <description>

**The 9 Types:**
| Emoji | Type      | What it covers |
|-------|-----------|----------------|
| 📦    | new       | Adding new features, files, or capabilities |
| 🔧    | update    | Changing existing code, refactoring, improvements |
| 🗑️    | remove    | Removing code, files, features, or dependencies |
| 🔒    | security  | Security fixes, patches, vulnerability resolutions |
| ⚙️    | setup     | Project configs, CI/CD, tooling, build systems |
| ☕    | chore     | Maintenance tasks, dependency updates, housekeeping |
| 🧪    | test      | Adding, updating, or fixing tests |
| 📖    | docs      | Documentation changes and updates |
| 🚀    | release   | Version releases and release preparation |

**Rules:**
- Use lowercase for type
- Use present tense ("add" not "added")
- No period at the end
- Keep description under 72 characters
- Include scope (filename) if appropriate

**Git Diff:**
\`\`\`diff
${diff}
\`\`\`

${filePath ? `**File:** ${filePath}\n` : ''}
Generate a single commit message following Clean Commit format. Return ONLY the commit message, nothing else.`,
  },

  conventional: {
    name: 'Conventional Commits',
    description: 'Standard Conventional Commits specification',
    buildPrompt: (diff, filePath) => `You are an expert at writing git commit messages following the "Conventional Commits" specification.

**Format:**
<type>(<scope>): <description>

**Types:**
- feat: A new feature
- fix: A bug fix
- docs: Documentation only changes
- style: Changes that don't affect code meaning (whitespace, formatting)
- refactor: Code change that neither fixes a bug nor adds a feature
- perf: Code change that improves performance
- test: Adding missing tests or correcting existing tests
- build: Changes that affect the build system or external dependencies
- ci: Changes to CI configuration files and scripts
- chore: Other changes that don't modify src or test files

**Rules:**
- Use lowercase for type
- Use present tense ("add" not "added")
- No period at the end
- Keep description under 72 characters
- Scope is optional but recommended

**Git Diff:**
\`\`\`diff
${diff}
\`\`\`

${filePath ? `**File:** ${filePath}\n` : ''}
Generate a single commit message following Conventional Commits format. Return ONLY the commit message, nothing else.`,
  },

  gitmoji: {
    name: 'Gitmoji',
    description: 'Gitmoji commit convention with emojis',
    buildPrompt: (diff, filePath) => `You are an expert at writing git commit messages using the "Gitmoji" convention.

**Format:**
:<emoji-code>: <description>

**Common Emoji Codes:**
- :sparkles: Introduce new features
- :bug: Fix a bug
- :recycle: Refactor code
- :lipstick: Update UI and style files
- :memo: Add or update documentation
- :rocket: Deploy stuff
- :white_check_mark: Add, update, or pass tests
- :lock: Fix security issues
- :arrow_up: Upgrade dependencies
- :arrow_down: Downgrade dependencies
- :fire: Remove code or files
- :construction: Work in progress

**Rules:**
- Start with emoji code (e.g., :sparkles:)
- Use present tense
- Keep concise and clear
- No period at the end

**Git Diff:**
\`\`\`diff
${diff}
\`\`\`

${filePath ? `**File:** ${filePath}\n` : ''}
Generate a single commit message using Gitmoji format. Return ONLY the commit message, nothing else.`,
  },

  simple: {
    name: 'Simple',
    description: 'Plain descriptive commit messages',
    buildPrompt: (diff, filePath) => `You are an expert at writing clear, concise git commit messages.

**Format:**
Simple descriptive message in imperative mood

**Rules:**
- Use imperative mood ("Add feature" not "Added feature")
- Start with capital letter
- No period at the end
- Keep under 72 characters
- Be specific and clear
- No prefixes or emojis

**Git Diff:**
\`\`\`diff
${diff}
\`\`\`

${filePath ? `**File:** ${filePath}\n` : ''}
Generate a single, clear commit message. Return ONLY the commit message, nothing else.`,
  },
};

export function getConvention(name = 'clean') {
  return CONVENTIONS[name] || CONVENTIONS.clean;
}

export function listConventions() {
  return Object.entries(CONVENTIONS).map(([key, conv]) => ({
    value: key,
    name: `${conv.name} - ${conv.description}`,
  }));
}
`...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **New Features**
  * Added multiple commit conventions (clean, conventional, gitmoji, simple) selectable via `--convention <type>` option.
  * New `config set-convention` command to set default commit convention.
  * Ability to regenerate commit messages with different conventions during the confirmation workflow (up to 5 attempts).
  * Enhanced commit confirmation display with convention details.

* **Bug Fixes**
  * Updated authentication to use GitHub CLI instead of token-based authentication.

<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Copilot AI and others added 3 commits January 31, 2026 08:54
Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement GitHub Copilot SDK integration with multiple conventions Implement Copilot SDK integration and multi-convention commit system Jan 31, 2026
Copilot AI requested a review from warengonzaga January 31, 2026 09:03
@warengonzaga warengonzaga marked this pull request as ready for review January 31, 2026 09:26
@coderabbitai
Copy link

coderabbitai bot commented Jan 31, 2026

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • ✅ Full review completed - (🔄 Check again to review again)

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements GitHub Copilot SDK integration and introduces a multi-convention commit message system with four supported formats: Clean Commit (default), Conventional Commits, Gitmoji, and Simple. The implementation replaces the placeholder Copilot integration with real SDK calls and adds interactive convention switching during the commit process.

Changes:

  • Adds pluggable convention system with four pre-configured formats and AI-specific prompts for each
  • Implements GitHub Copilot SDK client lifecycle management with automatic OpenAI fallback
  • Adds interactive convention switching capability with regeneration loops
  • Updates authentication to use GitHub CLI instead of token-based auth

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
source/utils/commit-conventions.js New file defining four commit conventions with format-specific prompts
source/providers/ai-provider.js Replaces placeholder with real Copilot SDK integration (CopilotClient lifecycle)
source/commands/commit.js Adds regeneration loops with convention switching for file-by-file and single-file workflows
source/commands/auth.js Removes token parameter, validates gh CLI installation and authentication status
source/commands/config.js Adds convention name display in config output
source/cli.js Adds --convention flag and set-convention subcommand with validation
source/utils/ui.js Adds promptConventionSelection and updates confirmCommit to show convention and regeneration option
source/utils/config-manager.js Adds setConvention/getConvention functions with 'clean' default
test.js Adds comprehensive tests for convention system and config management
Comments suppressed due to low confidence (1)

source/cli.js:64

		authenticateWithCopilot(options.token);

@warengonzaga
Copy link
Owner

@copilot apply changes based on the comments in this thread

Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.

Comments suppressed due to low confidence (1)

source/cli.js:65

		authenticateWithCopilot(options.token);


// Create session with model
const session = await client.createSession({
model: this.model || options.model || 'gpt-4.1',
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The model value 'gpt-4.1' on line 77 may not be a valid OpenAI model identifier. Standard OpenAI model names include 'gpt-4', 'gpt-4-turbo', 'gpt-4o', and 'gpt-3.5-turbo', but not 'gpt-4.1'. This could cause failures when the Copilot SDK or fallback OpenAI provider attempts to use this model.

Consider using 'gpt-4' or 'gpt-4o' as the default, or verify the correct model identifier for the GitHub Copilot SDK.

Suggested change
model: this.model || options.model || 'gpt-4.1',
model: this.model || options.model || 'gpt-4o',

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 5f3d2a6. Changed model from 'gpt-4.1' to 'gpt-4o', which is a valid OpenAI model identifier compatible with both Copilot SDK and OpenAI fallback.

Comment on lines 118 to 123
`GitHub Copilot failed: ${error.message}\n\n` +
'Make sure you have:\n' +
'1. GitHub Copilot subscription\n' +
'2. Authenticated via: gh auth login\n' +
'3. GitHub CLI installed and in PATH\n\n' +
'Or set OpenAI key as fallback: magicc auth openai <key>',
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message on lines 117-124 provides helpful troubleshooting steps, which is good. However, the message assumes the user needs to authenticate via gh auth login, but they may already be authenticated and the issue could be something else (e.g., no Copilot subscription, network issues, or SDK compatibility problems). Consider making the error message more diagnostic by checking what the actual error type is, or adding a note that if already authenticated, the issue might be elsewhere.

Suggested change
`GitHub Copilot failed: ${error.message}\n\n` +
'Make sure you have:\n' +
'1. GitHub Copilot subscription\n' +
'2. Authenticated via: gh auth login\n' +
'3. GitHub CLI installed and in PATH\n\n' +
'Or set OpenAI key as fallback: magicc auth openai <key>',
`GitHub Copilot failed` +
(error.name ? ` (${error.name})` : '') +
`: ${error.message}\n\n` +
'This may be caused by:\n' +
'1. Missing GitHub Copilot subscription\n' +
'2. Not being authenticated in GitHub CLI (try: gh auth login)\n' +
'3. Network issues or GitHub API availability problems\n' +
'4. Incompatible or outdated GitHub Copilot SDK or CLI version\n\n' +
'If the issue persists, you can also set an OpenAI key as a fallback: ' +
'magicc auth openai <key>',

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 5f3d2a6. Enhanced error message to be more diagnostic by including error.name and listing multiple possible causes (missing subscription, not authenticated, network issues, SDK compatibility) rather than assuming authentication is the only issue.

Comment on lines +15 to +16
| Emoji | Type | What it covers |
|-------|-----------|----------------|
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table formatting on lines 15-16 uses pipe characters to create a markdown table header. However, the pipes at the start of line 15 will be interpreted as part of the template string literal, not markdown. When this prompt is sent to the AI, it will receive:

| Emoji | Type      | What it covers |
|-------|-----------|----------------|

This is correct for markdown, but if the AI expects plain text formatting, this might not render as intended. Consider verifying that the AI models handle markdown table formatting correctly in prompts, or use plain text formatting for better compatibility.

Copilot uses AI. Check for mistakes.
// Show convention name nicely
if (key === 'convention') {
const conv = getConvention(value);
displayValue = `${value} (${conv.name})`;
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention display logic on lines 36-38 should handle cases where the convention value in config might be invalid or undefined. If a user manually edits their config file and sets an invalid convention name, calling getConvention(value) will return the 'clean' convention as fallback, but the display will show the invalid value alongside "Clean Commit". Consider adding validation or a clearer message when the stored convention is invalid.

Suggested change
displayValue = `${value} (${conv.name})`;
if (conv && typeof conv.name === 'string') {
// Prefer the resolved convention name; avoid showing invalid raw values
displayValue = conv.name;
} else {
displayValue = value ?? 'Unknown convention';
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 5f3d2a6. Added validation in config display to check if stored convention is valid using Object.keys(CONVENTIONS). Invalid conventions now show as "invalid - defaults to [fallback]" to make it clear the value is invalid.

Comment on lines +96 to +101
const validConventions = Object.keys(CONVENTIONS);
if (!validConventions.includes(type)) {
showError(`Invalid convention: ${type}`);
console.log(`Available: ${validConventions.join(', ')}`);
process.exit(1);
}
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation on lines 96-101 checks if the convention type is valid using Object.keys(CONVENTIONS), which is good. However, this validation is only enforced in the CLI set-convention command. The config-manager's setConvention function doesn't validate input, which means other code paths could potentially set invalid conventions. Consider adding validation in the config-manager itself to ensure consistency across all code paths.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 8e01b49. Added validation directly in setConvention() by importing CONVENTIONS and checking against valid convention names. Invalid conventions now trigger a warning and default to 'clean', ensuring consistency across all code paths (CLI commands, config display, and any other code that calls setConvention).

@warengonzaga
Copy link
Owner

@copilot apply changes based on the comments in this thread

Copilot AI and others added 2 commits February 1, 2026 04:39
Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
source/cli.js (1)

63-66: ⚠️ Potential issue | 🟡 Minor

Remove unused --token option.

The --token option is passed to authenticateWithCopilot() but the function no longer accepts parameters (see source/commands/auth.js line 22).

🔧 Remove the dead code
 authCmd
 	.command('copilot')
 	.description('Authenticate with GitHub Copilot')
-	.option('--token <token>', 'GitHub token')
-	.action(options => {
-		authenticateWithCopilot(options.token);
+	.action(() => {
+		authenticateWithCopilot();
 	});
source/commands/commit.js (1)

91-106: ⚠️ Potential issue | 🟡 Minor

Convention support missing in processAllFiles.

Unlike processFilesInteractively and processFile, this function:

  1. Doesn't pass the convention to generateCommitMessage (line 91)
  2. Doesn't pass the convention to confirmCommit for display (line 94)
  3. Doesn't support the regeneration flow when user selects "change-convention"

This means --all users won't see convention info or be able to regenerate with different conventions.

🔧 Suggested fix to add convention support
 export async function processAllFiles(aiProvider, options = {}) {
 	showInfo('Processing all files together...');
 
 	// Stage all changes
 	await stageAll();
 
 	// Get full diff
 	const diff = await getDiff();
 	if (!diff) {
 		showWarning('No changes to commit.');
 		return;
 	}
 
+	let currentConvention = options.convention || getConvention();
+	let attempts = 0;
+	const maxAttempts = 5;
+
+	while (attempts < maxAttempts) {
-	// Generate commit message
-	showInfo('Generating commit message...');
-	const message = await aiProvider.generateCommitMessage(diff, null, options);
+		showInfo('Generating commit message...');
+		const message = await aiProvider.generateCommitMessage(diff, null, {
+			...options,
+			convention: currentConvention,
+		});
 
-	// Confirm and commit
-	const result = await confirmCommit(message);
+		const result = await confirmCommit(message, null, currentConvention);
 
-	if (result.action === 'accept') {
-		const success = await commit(result.message);
-		if (success) {
-			showSuccess('Changes committed successfully!');
-			console.log(`📝 ${result.message}`);
-		} else {
-			showError('Failed to commit changes.');
+		if (result.action === 'accept') {
+			const success = await commit(result.message);
+			if (success) {
+				showSuccess('Changes committed successfully!');
+				console.log(`📝 ${result.message}`);
+			} else {
+				showError('Failed to commit changes.');
+			}
+			return;
+		} else if (result.action === 'regenerate') {
+			currentConvention = result.convention;
+			attempts++;
+			continue;
+		} else if (result.action === 'skip') {
+			showInfo('Commit cancelled.');
+			return;
 		}
-	} else if (result.action === 'skip') {
-		showInfo('Commit cancelled.');
 	}
+
+	showWarning('Maximum regeneration attempts reached.');
 }
🤖 Fix all issues with AI agents
In `@source/commands/auth.js`:
- Around line 22-24: The CLI's --token option is unused because
authenticateWithCopilot() in source/commands/auth.js no longer accepts a token;
either remove the dead option from the CLI or update the function to accept and
use it — locate authenticateWithCopilot and the CLI registration of the "auth
copilot" command (options.token passed in source/cli.js) and do one of: (A)
delete the --token option from the command definition in source/cli.js and any
references to options.token, or (B) change authenticateWithCopilot to accept a
token parameter (e.g., authenticateWithCopilot(token) or an options object) and
thread options.token from the CLI into that function and use it where
authentication requires a token.
🧹 Nitpick comments (2)
source/utils/config-manager.js (1)

21-26: Consider logging or returning feedback when ignoring unsupported providers.

setToken silently ignores any provider other than 'openai'. While this aligns with the PR's goal to remove Copilot token handling, callers have no way to know if their token was stored. Consider either throwing an error for unsupported providers or returning a boolean to indicate success.

♻️ Optional: Add feedback for unsupported providers
 export function setToken(provider, token) {
 	if (provider === 'openai') {
 		config.set('openai', token);
 		config.set('authenticatedAt', new Date().toISOString());
+		return true;
 	}
+	return false;
 }
source/cli.js (1)

49-52: Consider validating --convention option at CLI level.

The --convention option is validated in set-convention but not when passed to the commit command. While downstream code handles unknown conventions by falling back to 'clean', users won't get immediate feedback about typos.

♻️ Optional: Add validation for --convention option
 	.option(
 		'--convention <type>',
 		'Commit convention (clean, conventional, gitmoji, simple)',
 	)
 	.action(options => {
+		if (options.convention && !Object.keys(CONVENTIONS).includes(options.convention)) {
+			showError(`Invalid convention: ${options.convention}`);
+			console.log(`Available: ${Object.keys(CONVENTIONS).join(', ')}`);
+			process.exit(1);
+		}
 		commitCommand(options);
 	});

Comment on lines +22 to +24
export async function authenticateWithCopilot() {
try {
// Check for token in arguments first
let authToken = token;
console.log('🔐 Setting up GitHub Copilot authentication...\n');
Copy link

@coderabbitai coderabbitai bot Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Function signature mismatch: --token option is ignored.

authenticateWithCopilot() no longer accepts a token parameter, but the CLI still passes options.token (see source/cli.js line 65). The --token <token> option on the auth copilot command is now dead code.

Either remove the --token option from the CLI or update this function to use it if there's a future use case.

🔧 Option 1: Remove the unused --token option from cli.js

In source/cli.js:

 authCmd
 	.command('copilot')
 	.description('Authenticate with GitHub Copilot')
-	.option('--token <token>', 'GitHub token')
-	.action(options => {
-		authenticateWithCopilot(options.token);
+	.action(() => {
+		authenticateWithCopilot();
 	});
🤖 Prompt for AI Agents
In `@source/commands/auth.js` around lines 22 - 24, The CLI's --token option is
unused because authenticateWithCopilot() in source/commands/auth.js no longer
accepts a token; either remove the dead option from the CLI or update the
function to accept and use it — locate authenticateWithCopilot and the CLI
registration of the "auth copilot" command (options.token passed in
source/cli.js) and do one of: (A) delete the --token option from the command
definition in source/cli.js and any references to options.token, or (B) change
authenticateWithCopilot to accept a token parameter (e.g.,
authenticateWithCopilot(token) or an options object) and thread options.token
from the CLI into that function and use it where authentication requires a
token.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot can you apply this suggestion?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Co-authored-by: warengonzaga <15052701+warengonzaga@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants