Enhance CLI list command with detailed effective state and reason display (#39)
This commit is contained in:
commit
62a8a80fc5
@ -149,8 +149,16 @@ function handleListCommand(rawArgs) {
|
||||
const availableItems = getAllAvailableItems(section);
|
||||
|
||||
// Count effectively enabled items
|
||||
const effectivelyEnabled = Object.values(effectiveStates[section] || {})
|
||||
let effectivelyEnabled;
|
||||
if (section === "collections") {
|
||||
// For collections, count explicitly enabled ones
|
||||
effectivelyEnabled = Object.values(sanitizedConfig[section] || {})
|
||||
.filter(value => value === true).length;
|
||||
} else {
|
||||
// For other sections, count effectively enabled items
|
||||
effectivelyEnabled = Object.values(effectiveStates[section] || {})
|
||||
.filter(state => state.enabled).length;
|
||||
}
|
||||
|
||||
const { totalCharacters } = calculateSectionFootprint(section, sanitizedConfig[section]);
|
||||
const headingParts = [
|
||||
@ -170,20 +178,40 @@ function handleListCommand(rawArgs) {
|
||||
|
||||
// Show items with effective state and reason
|
||||
if (section === "collections") {
|
||||
// Collections show simple enabled/disabled
|
||||
// Collections show simple enabled/disabled with count of effectively enabled items
|
||||
availableItems.forEach(itemName => {
|
||||
const isEnabled = Boolean(sanitizedConfig[section]?.[itemName]);
|
||||
console.log(` [${isEnabled ? "✓" : " "}] ${itemName}`);
|
||||
|
||||
// Count how many items this collection would enable
|
||||
let enabledCount = 0;
|
||||
if (isEnabled) {
|
||||
// Simulate what would happen if only this collection was enabled
|
||||
const testConfig = { collections: { [itemName]: true } };
|
||||
const testEffectiveStates = computeEffectiveItemStates(testConfig);
|
||||
|
||||
for (const sectionName of ["prompts", "instructions", "chatmodes"]) {
|
||||
enabledCount += Object.values(testEffectiveStates[sectionName] || {})
|
||||
.filter(state => state.enabled && state.reason === "collection").length;
|
||||
}
|
||||
}
|
||||
|
||||
const countText = isEnabled ? ` (${enabledCount} items effectively enabled)` : "";
|
||||
console.log(` [${isEnabled ? "✓" : " "}] ${itemName}${countText}`);
|
||||
});
|
||||
} else {
|
||||
// Other sections show effective state with reason
|
||||
// Other sections show effective state with detailed reason
|
||||
availableItems.forEach(itemName => {
|
||||
const effectiveState = effectiveStates[section]?.[itemName];
|
||||
if (effectiveState) {
|
||||
const symbol = effectiveState.enabled ? "✓" : " ";
|
||||
const reasonText = effectiveState.reason === "explicit"
|
||||
? ` (${effectiveState.reason})`
|
||||
: effectiveState.enabled ? ` (${effectiveState.reason})` : "";
|
||||
let reasonText = "";
|
||||
|
||||
if (effectiveState.reason === "explicit") {
|
||||
reasonText = ` (explicit:${effectiveState.enabled})`;
|
||||
} else if (effectiveState.reason === "collection" && effectiveState.collections && effectiveState.collections.length > 0) {
|
||||
reasonText = ` (via:[${effectiveState.collections.join(',')}])`;
|
||||
}
|
||||
|
||||
console.log(` [${symbol}] ${itemName}${reasonText}`);
|
||||
} else {
|
||||
console.log(` [ ] ${itemName}`);
|
||||
|
||||
@ -214,14 +214,21 @@ function computeEffectiveItemStates(config) {
|
||||
chatmodes: {}
|
||||
};
|
||||
|
||||
// Build membership maps: Map<itemName, Set<collectionName>> per section for O(1) lookups
|
||||
// Build detailed membership maps: Map<itemName, Set<collectionName>> per section
|
||||
const collectionMemberships = {
|
||||
prompts: new Map(),
|
||||
instructions: new Map(),
|
||||
chatmodes: new Map()
|
||||
};
|
||||
|
||||
// Build simple enabled sets for O(1) lookups
|
||||
const collectionEnabledItems = {
|
||||
prompts: new Set(),
|
||||
instructions: new Set(),
|
||||
chatmodes: new Set()
|
||||
};
|
||||
|
||||
// Identify enabled collections per section
|
||||
// Identify enabled collections per section and track memberships
|
||||
if (config.collections) {
|
||||
for (const [collectionName, enabled] of Object.entries(config.collections)) {
|
||||
if (enabled === true) {
|
||||
@ -233,12 +240,24 @@ function computeEffectiveItemStates(config) {
|
||||
// Extract item name from path - remove directory and all extensions
|
||||
const itemName = path.basename(item.path).replace(/\.(prompt|instructions|chatmode)\.md$/, '');
|
||||
|
||||
let sectionName;
|
||||
if (item.kind === "prompt") {
|
||||
collectionEnabledItems.prompts.add(itemName);
|
||||
sectionName = "prompts";
|
||||
} else if (item.kind === "instruction") {
|
||||
collectionEnabledItems.instructions.add(itemName);
|
||||
sectionName = "instructions";
|
||||
} else if (item.kind === "chat-mode") {
|
||||
collectionEnabledItems.chatmodes.add(itemName);
|
||||
sectionName = "chatmodes";
|
||||
}
|
||||
|
||||
if (sectionName) {
|
||||
// Track which collections enable this item
|
||||
if (!collectionMemberships[sectionName].has(itemName)) {
|
||||
collectionMemberships[sectionName].set(itemName, new Set());
|
||||
}
|
||||
collectionMemberships[sectionName].get(itemName).add(collectionName);
|
||||
|
||||
// Add to enabled set for O(1) lookups
|
||||
collectionEnabledItems[sectionName].add(itemName);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -258,6 +277,7 @@ function computeEffectiveItemStates(config) {
|
||||
for (const itemName of availableItems) {
|
||||
const explicitValue = sectionConfig[itemName];
|
||||
const isEnabledByCollection = collectionEnabled.has(itemName);
|
||||
const enablingCollections = collectionMemberships[section].get(itemName) || new Set();
|
||||
|
||||
// Precedence rules with strict undefined handling:
|
||||
// 1. If explicitly set to true or false, use that value (highest priority)
|
||||
@ -269,6 +289,7 @@ function computeEffectiveItemStates(config) {
|
||||
|
||||
let enabled = false;
|
||||
let reason = "disabled";
|
||||
let collections = [];
|
||||
|
||||
if (explicitValue === true) {
|
||||
enabled = true;
|
||||
@ -281,9 +302,10 @@ function computeEffectiveItemStates(config) {
|
||||
// undefined values can be enabled by collections (not treated as disabled)
|
||||
enabled = true;
|
||||
reason = "collection";
|
||||
collections = Array.from(enablingCollections).sort();
|
||||
}
|
||||
|
||||
effectiveStates[section][itemName] = { enabled, reason };
|
||||
effectiveStates[section][itemName] = { enabled, reason, collections };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ async function runTests() {
|
||||
|
||||
const result = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(result.success, 'List should succeed');
|
||||
assert(result.stdout.includes('(collection)'), 'Should show collection reason');
|
||||
assert(result.stdout.includes('(via:[testing-automation])'), 'Should show collection reason');
|
||||
assert(result.stdout.includes('[✓]'), 'Should show enabled items');
|
||||
});
|
||||
|
||||
@ -105,7 +105,7 @@ async function runTests() {
|
||||
assert(result.success, 'Individual toggle should succeed');
|
||||
|
||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'),
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit:false)'),
|
||||
'Explicitly disabled item should show explicit reason');
|
||||
});
|
||||
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
# Awesome Copilot Configuration File
|
||||
# Manual test for effective state computation
|
||||
#
|
||||
# Testing precedence rules with undefined values
|
||||
|
||||
version: "1.0"
|
||||
project:
|
||||
name: "Test Project"
|
||||
description: "Testing effective state precedence"
|
||||
output_directory: ".github"
|
||||
collections:
|
||||
testing-automation: false
|
||||
prompts:
|
||||
ai-prompt-engineering-safety-review: false
|
||||
playwright-generate-test: true
|
||||
instructions:
|
||||
chatmodes:
|
||||
@ -1,35 +0,0 @@
|
||||
# Awesome Copilot Configuration File
|
||||
# Generated on 2025-09-21T22:44:51.675Z
|
||||
#
|
||||
# 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:
|
||||
playwright-generate-test: false
|
||||
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: true
|
||||
@ -119,14 +119,14 @@ async function runTests() {
|
||||
|
||||
// Check it's explicitly disabled
|
||||
const listResult1 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult1.stdout.includes('create-readme (explicit)'), 'Should show explicit disabled');
|
||||
assert(listResult1.stdout.includes('create-readme (explicit:false)'), 'Should show explicit disabled');
|
||||
|
||||
// Force enable all with --all flag
|
||||
await runCommand(`node awesome-copilot.js toggle prompts all on --all --config ${TEST_CONFIG}`);
|
||||
|
||||
// Check it's now explicitly enabled
|
||||
const listResult2 = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult2.stdout.includes('create-readme (explicit)') && listResult2.stdout.includes('[✓]'), 'Should be explicitly enabled');
|
||||
assert(listResult2.stdout.includes('create-readme (explicit:true)') && listResult2.stdout.includes('[✓]'), 'Should be explicitly enabled');
|
||||
});
|
||||
|
||||
// Test 4: File cleanup on disable
|
||||
@ -180,7 +180,7 @@ async function runTests() {
|
||||
|
||||
// Double-check with list command
|
||||
const listResult = await runCommand(`node awesome-copilot.js list prompts --config ${TEST_CONFIG}`);
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit)'), "'playwright-generate-test (explicit)' should be present in the list output");
|
||||
assert(listResult.stdout.includes('playwright-generate-test (explicit:false)'), "'playwright-generate-test (explicit:false)' should be present in the list output");
|
||||
assert(!listResult.stdout.includes('[✓] playwright-generate-test'), "'[✓] playwright-generate-test' should NOT be present in the list output (should remain explicitly disabled)");
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user