From fa18a762628847f5cd23622c7de9fe5a7722c3b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Sep 2025 23:50:03 +0000 Subject: [PATCH 1/7] Initial plan From 88e13bc74ef6104fbc47af6c66d7edd7865f69c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Sep 2025 23:50:04 +0000 Subject: [PATCH 2/7] Initial plan From 980fded5cd59b30de24492c66a3172f3dadf6716 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Sep 2025 23:53:39 +0000 Subject: [PATCH 3/7] TASK-005: Replace manual Set creation with precomputed getEffectivelyEnabledItems Co-authored-by: AstroSteveo <34114851+AstroSteveo@users.noreply.github.com> --- .../playwright-generate-test.prompt.md | 19 +++++++++++++++++ apply-config.js | 21 +++---------------- 2 files changed, 22 insertions(+), 18 deletions(-) create mode 100644 .github/prompts/playwright-generate-test.prompt.md diff --git a/.github/prompts/playwright-generate-test.prompt.md b/.github/prompts/playwright-generate-test.prompt.md new file mode 100644 index 0000000..65a6f99 --- /dev/null +++ b/.github/prompts/playwright-generate-test.prompt.md @@ -0,0 +1,19 @@ +--- +mode: agent +description: 'Generate a Playwright test based on a scenario using Playwright MCP' +tools: ['changes', 'codebase', 'editFiles', 'fetch', 'findTestFiles', 'problems', 'runCommands', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure', 'playwright'] +model: 'Claude Sonnet 4' +--- + +# Test Generation with Playwright MCP + +Your goal is to generate a Playwright test based on the provided scenario after completing all prescribed steps. + +## Specific Instructions + +- You are given a scenario, and you need to generate a playwright test for it. If the user does not provide a scenario, you will ask them to provide one. +- DO NOT generate test code prematurely or based solely on the scenario without completing all prescribed steps. +- DO run steps one by one using the tools provided by the Playwright MCP. +- Only after all steps are completed, emit a Playwright TypeScript test that uses `@playwright/test` based on message history +- Save generated test file in the tests directory +- Execute the test file and iterate until the test passes diff --git a/apply-config.js b/apply-config.js index b1e5c65..9000d35 100755 --- a/apply-config.js +++ b/apply-config.js @@ -101,25 +101,10 @@ async function applyConfig(configPath = "awesome-copilot.config.yml") { }; // Import config manager for effective state computation - const { computeEffectiveItemStates } = require("./config-manager"); + const { getEffectivelyEnabledItems } = require("./config-manager"); - // Compute effective states using precedence rules - const effectiveStates = computeEffectiveItemStates(config); - - // Create sets of effectively enabled items for performance - const effectivelyEnabledSets = { - prompts: new Set(), - instructions: new Set(), - chatmodes: new Set() - }; - - for (const section of ["prompts", "instructions", "chatmodes"]) { - for (const [itemName, state] of Object.entries(effectiveStates[section])) { - if (state.enabled) { - effectivelyEnabledSets[section].add(itemName); - } - } - } + // Get precomputed sets of effectively enabled items for O(1) performance + const effectivelyEnabledSets = getEffectivelyEnabledItems(config); // Count enabled collections for summary if (config.collections) { From 47a4117c6cb05a06d46b3047392793694c86bec9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Sep 2025 23:54:21 +0000 Subject: [PATCH 4/7] Clean up: remove test-generated file from .github/prompts --- .../playwright-generate-test.prompt.md | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .github/prompts/playwright-generate-test.prompt.md diff --git a/.github/prompts/playwright-generate-test.prompt.md b/.github/prompts/playwright-generate-test.prompt.md deleted file mode 100644 index 65a6f99..0000000 --- a/.github/prompts/playwright-generate-test.prompt.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -mode: agent -description: 'Generate a Playwright test based on a scenario using Playwright MCP' -tools: ['changes', 'codebase', 'editFiles', 'fetch', 'findTestFiles', 'problems', 'runCommands', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure', 'playwright'] -model: 'Claude Sonnet 4' ---- - -# Test Generation with Playwright MCP - -Your goal is to generate a Playwright test based on the provided scenario after completing all prescribed steps. - -## Specific Instructions - -- You are given a scenario, and you need to generate a playwright test for it. If the user does not provide a scenario, you will ask them to provide one. -- DO NOT generate test code prematurely or based solely on the scenario without completing all prescribed steps. -- DO run steps one by one using the tools provided by the Playwright MCP. -- Only after all steps are completed, emit a Playwright TypeScript test that uses `@playwright/test` based on message history -- Save generated test file in the tests directory -- Execute the test file and iterate until the test passes From 9322791733011a9ca07a8c495132d2f6210d14d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Sep 2025 23:55:42 +0000 Subject: [PATCH 5/7] Complete TASK-006: Add comprehensive documentation and tests for strict undefined handling Co-authored-by: AstroSteveo <34114851+AstroSteveo@users.noreply.github.com> --- config-manager.js | 21 ++++++++++++++----- test-effective-states.js | 45 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/config-manager.js b/config-manager.js index d1b6a10..da5280b 100644 --- a/config-manager.js +++ b/config-manager.js @@ -185,11 +185,17 @@ function generateConfigHash(config) { * Compute effective item states respecting explicit overrides over collections * * This function builds membership maps per section and returns effectively enabled items with reasons. - * It uses the following precedence rules: - * 1. Explicit true/false overrides everything (highest priority) + * It uses strict comparisons to ensure undefined values are never treated as explicitly disabled. + * + * Precedence rules with strict undefined handling: + * 1. Explicit true/false overrides everything (highest priority) - uses strict === comparisons * 2. If undefined and enabled by collection, use true * 3. Otherwise, use false (disabled) * + * CRITICAL: Only values that are strictly === false are treated as explicitly disabled. + * undefined, null, 0, '', or other falsy values are NOT treated as explicit disabling. + * This allows collections to enable items that are not explicitly configured. + * * @param {Object} config - Configuration object with sections * @returns {Object} Effective states for each section with { itemName: { enabled: boolean, reason: string } } * Reason can be: 'explicit', 'collection', or 'disabled' @@ -248,10 +254,13 @@ function computeEffectiveItemStates(config) { const explicitValue = sectionConfig[itemName]; const isEnabledByCollection = collectionEnabled.has(itemName); - // Precedence rules: - // 1. If explicitly set to true or false, use that value + // Precedence rules with strict undefined handling: + // 1. If explicitly set to true or false, use that value (highest priority) // 2. If undefined and enabled by collection, use true - // 3. Otherwise, use false + // 3. Otherwise, use false (disabled) + // + // IMPORTANT: Only strict === false comparisons are used to determine explicit disabling. + // undefined values are NEVER treated as explicitly disabled, allowing collections to enable them. let enabled = false; let reason = "disabled"; @@ -260,9 +269,11 @@ function computeEffectiveItemStates(config) { enabled = true; reason = "explicit"; } else if (explicitValue === false) { + // Strict comparison ensures only explicit false disables items enabled = false; reason = "explicit"; } else if (explicitValue === undefined && isEnabledByCollection) { + // undefined values can be enabled by collections (not treated as disabled) enabled = true; reason = "collection"; } diff --git a/test-effective-states.js b/test-effective-states.js index 621f04b..909303b 100644 --- a/test-effective-states.js +++ b/test-effective-states.js @@ -164,7 +164,50 @@ function runTests() { 'Chat mode should be enabled by collection'); }); - // Test 8: getEffectivelyEnabledItems returns Sets format + // Test 9: TASK-006 - Strict false checks prevent undefined treated as disabled + test("TASK-006: Strict false checks prevent undefined treated as disabled", () => { + const config = { + prompts: { + 'explicit-false-item': false, + 'explicit-true-item': true, + // 'undefined-item' is undefined (not set) + }, + collections: { + 'testing-automation': true + } + }; + const result = computeEffectiveItemStates(config); + + // Explicit false should be disabled with reason 'explicit' + const explicitFalse = result.prompts['explicit-false-item']; + if (explicitFalse) { + assert(explicitFalse.reason === 'explicit' && !explicitFalse.enabled, + 'Items with explicit false should be disabled with reason explicit'); + } + + // Explicit true should be enabled with reason 'explicit' + const explicitTrue = result.prompts['explicit-true-item']; + if (explicitTrue) { + assert(explicitTrue.reason === 'explicit' && explicitTrue.enabled, + 'Items with explicit true should be enabled with reason explicit'); + } + + // Undefined item in collection should be enabled with reason 'collection' + const undefinedInCollection = result.prompts['playwright-generate-test']; + if (undefinedInCollection) { + assert(undefinedInCollection.reason === 'collection' && undefinedInCollection.enabled, + 'Undefined items should be enabled by collections, not treated as explicitly disabled'); + } + + // Undefined item NOT in collection should be disabled with reason 'disabled' (not 'explicit') + const undefinedNotInCollection = result.prompts['some-random-item-not-in-any-collection']; + if (undefinedNotInCollection) { + assert(undefinedNotInCollection.reason === 'disabled' && !undefinedNotInCollection.enabled, + 'Undefined items not in collections should have reason disabled, not explicit'); + } + }); + + // Test 10: getEffectivelyEnabledItems returns Sets format test("getEffectivelyEnabledItems returns Sets format", () => { const config = { prompts: { From 497cd50a0fea16b6bdb48db2b59ba3dd4ab75278 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Sep 2025 23:56:24 +0000 Subject: [PATCH 6/7] Fix undefined item flags being converted to false in toBoolean function Co-authored-by: AstroSteveo <34114851+AstroSteveo@users.noreply.github.com> --- config-manager.js | 5 +++++ test-effective-states.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/config-manager.js b/config-manager.js index d1b6a10..952adb6 100644 --- a/config-manager.js +++ b/config-manager.js @@ -101,6 +101,11 @@ function toBoolean(value) { if (normalized === "false") return false; } + // Preserve undefined as undefined for "no explicit override" + if (value === undefined) { + return undefined; + } + return Boolean(value); } diff --git a/test-effective-states.js b/test-effective-states.js index 621f04b..5f832b1 100644 --- a/test-effective-states.js +++ b/test-effective-states.js @@ -214,6 +214,37 @@ function runTests() { assert(result.prompts.size > 0, 'Should have enabled prompts'); }); + // Test 10: Undefined values are not treated as explicitly disabled (TASK-004) + test("Undefined values are not treated as explicitly disabled", () => { + const config = { + prompts: { + 'playwright-generate-test': true, // explicit true + 'csharp-nunit': false, // explicit false + // 'playwright-explore-website' is undefined (not mentioned) + }, + collections: { + 'testing-automation': true + } + }; + + const result = computeEffectiveItemStates(config); + + // Explicit true should be explicit + const explicitTrue = result.prompts['playwright-generate-test']; + assert(explicitTrue && explicitTrue.enabled && explicitTrue.reason === 'explicit', + 'Explicit true should be enabled with explicit reason'); + + // Explicit false should be explicit (strict === false comparison) + const explicitFalse = result.prompts['csharp-nunit']; + assert(explicitFalse && !explicitFalse.enabled && explicitFalse.reason === 'explicit', + 'Explicit false should be disabled with explicit reason'); + + // Undefined should inherit from collection + const undefinedItem = result.prompts['playwright-explore-website']; + assert(undefinedItem && undefinedItem.enabled && undefinedItem.reason === 'collection', + 'Undefined items should inherit from collection, not be treated as explicitly disabled'); + }); + console.log(`\nTest Results: ${passedTests}/${totalTests} passed`); if (passedTests === totalTests) { From 3f6f0291f0147ec3c309628271048bc201732e7f Mon Sep 17 00:00:00 2001 From: AstroSteveo <34114851+AstroSteveo@users.noreply.github.com> Date: Tue, 23 Sep 2025 20:05:54 -0500 Subject: [PATCH 7/7] fix: change path for instructions for this repo only --- .vscode/settings.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index dbb05b4..c01085e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ { "chat.modeFilesLocations": { - ".github/chatmodes": true + "chatmodes": true }, "chat.promptFilesLocations": { - ".github/prompts": true + "prompts": true }, "chat.instructionsFilesLocations": { - ".github/instructions": true + "instructions": true } -} \ No newline at end of file +}