diff --git a/.github/agents/tsh-business-analyst.agent.md b/.github/agents/tsh-business-analyst.agent.md index 68a2b6db..4ce73f4b 100644 --- a/.github/agents/tsh-business-analyst.agent.md +++ b/.github/agents/tsh-business-analyst.agent.md @@ -18,6 +18,8 @@ You are a thin orchestrator — your primary job is to coordinate the skills tha Your output is **business-oriented**. You produce epics and stories that stakeholders can understand without technical knowledge. You include high-level technical notes only when they were explicitly discussed during the workshop. +You are also responsible for ensuring acceptance criteria are **test-ready** before handoff to QA. This means every user story's AC must define clear expected outcomes, identifiable preconditions, and explicit boundaries or constraints. If QA redirects a task back due to incomplete AC, you own the gap resolution. Use `tsh-task-analysing` (Step 3b) to validate and complete AC before QA consumes them. + You do NOT produce: - Technical specifications or architecture decisions (those are the responsibility of `tsh-architect`) - Detailed requirement research or gap analysis (those are the responsibility of `tsh-context-engineer`) @@ -60,6 +62,7 @@ This policy is the **single source of truth** for the protected status list. All - `tsh-jira-task-formatting` - to format extracted tasks into Jira-ready structure following the benchmark template, manage review gates, and guide Jira issue creation. Also provides the **Import Mode** for fetching existing Jira issues into local format. Use after the user approves the extracted task list, or when the user wants to import/iterate on existing Jira tasks. - `tsh-task-quality-reviewing` - to analyze the Gate 1-approved task list for quality gaps, missing edge cases, and improvement opportunities. Runs automatically after Gate 1 approval. Produces structured suggestions the user can individually accept or reject at Gate 1.5, then applies accepted changes to `extracted-tasks.md`. - `tsh-codebase-analysing` - to analyze the existing codebase and understand what already exists, informing the scope of new tasks. Use during material analysis when codebase context is relevant. +- `tsh-task-analysing` - to analyse task context, gather information from multiple sources, identify gaps, and ensure acceptance criteria are test-ready before handoff to QA workflows. Use when a task needs deeper requirement analysis or when QA reports incomplete AC. ## Parallel Processing Strategy diff --git a/.github/agents/tsh-engineering-manager.agent.md b/.github/agents/tsh-engineering-manager.agent.md index bf5b3503..3f7b6896 100644 --- a/.github/agents/tsh-engineering-manager.agent.md +++ b/.github/agents/tsh-engineering-manager.agent.md @@ -15,7 +15,7 @@ tools: ] agents: [ - "tsh-e2e-engineer", + "tsh-qa-engineer", "tsh-software-engineer", "tsh-devops-engineer", "tsh-architect", @@ -48,7 +48,7 @@ If there is no code review or verification phase defined in the plan, you ensure ## Agents Delegation Guidelines -You have access to the `tsh-e2e-engineer` agent. +You have access to the `tsh-qa-engineer` agent. - **MUST delegate to when**: - Implementing end-to-end tests for features that require comprehensive testing of user flows and interactions across the entire application. @@ -69,7 +69,7 @@ You have access to the `tsh-software-engineer` agent. - Always run subagent with [tsh-implement-ui-common-task.prompt.md](../internal-prompts/tsh-implement-ui-common-task.prompt.md) prompt when implementing frontend features based on Figma designs. This prompt handles implementation only — UI verification against Figma is orchestrated separately by you (the manager) via `tsh-ui-reviewer`. - Always run subagent with [tsh-implement-common-task.prompt.md](../internal-prompts/tsh-implement-common-task.prompt.md) prompt for backend and non-Figma related frontend tasks to ensure that the implementation follows the standard implementation workflow defined in that prompt. - **SHOULD NOT delegate to**: - - Implementing e2e tests - delegate those to `tsh-e2e-engineer` agent for better test design and implementation. + - Implementing e2e tests - delegate those to `tsh-qa-engineer` agent for better test design and implementation. - Implementing infrastructure and DevOps tasks - delegate those to `tsh-devops-engineer` agent for better expertise in cloud and infrastructure automation. You have access to the `tsh-devops-engineer` agent. diff --git a/.github/agents/tsh-e2e-engineer.agent.md b/.github/agents/tsh-qa-engineer.agent.md similarity index 92% rename from .github/agents/tsh-e2e-engineer.agent.md rename to .github/agents/tsh-qa-engineer.agent.md index d47a6054..585dec47 100644 --- a/.github/agents/tsh-e2e-engineer.agent.md +++ b/.github/agents/tsh-qa-engineer.agent.md @@ -1,6 +1,6 @@ --- -description: "Agent specializing in creating, maintaining, and debugging end-to-end tests using Playwright." -tools: ['execute', 'read', 'atlassian/search', 'context7/*', 'figma-mcp-server/*', 'playwright/*', 'sequential-thinking/*', 'edit', 'search', 'todo', 'agent', 'vscode/runCommand', 'vscode/openSimpleBrowser', 'vscode/askQuestions'] +description: "Agent specializing in quality assurance — E2E testing with Playwright, manual test planning, regression analysis, bug reporting, and accessibility auditing." +tools: ['execute', 'read', 'atlassian/*', 'context7/*', 'figma-mcp-server/*', 'playwright/*', 'sequential-thinking/*', 'edit', 'search', 'todo', 'agent', 'vscode/runCommand', 'vscode/openSimpleBrowser', 'vscode/askQuestions'] handoffs: - label: Report critical bug found during testing agent: tsh-software-engineer @@ -10,7 +10,7 @@ handoffs: ## Agent Role and Responsibilities -Role: You are an E2E Test Engineer responsible for creating, maintaining, and debugging end-to-end tests using Playwright based on provided requirements and implementation plans. You write tests that are **reliable** (no flaky), **maintainable** (Page Objects), **fast** (parallel), and **meaningful** (catch real bugs). +Role: You are a QA Engineer responsible for end-to-end quality — from test planning and manual test case design through E2E automation with Playwright, regression risk analysis, bug reporting, and accessibility auditing. You write tests that are **reliable** (no flaky), **maintainable** (Page Objects), **fast** (parallel), and **meaningful** (catch real bugs). You are **non-interactive** - make reasonable decisions and document them. diff --git a/.github/agents/tsh-software-engineer.agent.md b/.github/agents/tsh-software-engineer.agent.md index 407d8be1..f5950026 100644 --- a/.github/agents/tsh-software-engineer.agent.md +++ b/.github/agents/tsh-software-engineer.agent.md @@ -23,7 +23,7 @@ handoffs: prompt: /tsh-review Review the implementation against the plan and feature context send: false - label: Write E2E Tests - agent: tsh-e2e-engineer + agent: tsh-qa-engineer prompt: /tsh-implement-e2e Create E2E tests for the implemented feature send: false --- diff --git a/.github/instructions/tsh-atlassian-mcp.instructions.md b/.github/instructions/tsh-atlassian-mcp.instructions.md new file mode 100644 index 00000000..10e8800e --- /dev/null +++ b/.github/instructions/tsh-atlassian-mcp.instructions.md @@ -0,0 +1,303 @@ +--- +description: 'Correct tool call patterns for Atlassian MCP (Jira and Confluence). Prevents wasted retries on parameter errors and reduces token usage from verbose API responses.' +applyTo: '.github/**' +--- + +# Atlassian MCP Tool Usage Patterns + +## Session Setup — Get `cloudId` First + +Every Atlassian MCP tool requires a `cloudId`. Fetch it **once** at the start of any Jira/Confluence workflow and reuse it for all subsequent calls: + +``` +mcp_atlassian_getAccessibleAtlassianResources() +→ returns array of resources with { id, url, name } +→ use the `id` field as `cloudId` for all other calls +``` + +If multiple resources are returned, ask the user which one to use. + +## Fetching Known Tickets — Never Use Rovo Search + +When the input matches a Jira issue key pattern (`[A-Z]+-\d+`), **always** use `getJiraIssue` directly. Never use `mcp_atlassian_search` (Rovo) to retrieve a known ticket — Rovo returns only titles and text snippets, not structured fields (description, AC, status, type). + +**Correct path for a known ticket:** +1. `getAccessibleAtlassianResources` → `cloudId` (skip if already cached) +2. `getJiraIssue(cloudId, issueKey)` → full structured fields + +**Fallback when `getJiraIssue` is unavailable or disabled:** +If `getJiraIssue` cannot be called, use `mcp_atlassian_fetch` with the REST API URL directly: +``` +mcp_atlassian_fetch(url: "https://{instance}.atlassian.net/rest/api/3/issue/{issueKey}") +``` +This returns the same full JSON payload (description, status, type, etc.) as `getJiraIssue`. + +**Use `mcp_atlassian_search` (Rovo) only when:** +- You need to discover related content across Jira + Confluence (e.g., "find bugs related to firmware") +- The user provides a natural-language query, not a ticket key +- You need to find Confluence pages linked to a topic + +## Creating Jira Issues and Sub-Tasks + +Use `mcp_atlassian_createJiraIssue` with these **exact parameter names**: + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `cloudId` | Yes | From `getAccessibleAtlassianResources` | +| `projectKey` | Yes | e.g., `"PROJ"` | +| `issueTypeName` | Yes | Exact name from project metadata, e.g., `"Sub task"`, `"Task"`, `"Bug"` | +| `summary` | Yes | Issue title | +| `description` | No | Issue body (markdown). Put the **full content** here — do not use a placeholder and add content later as a comment. | +| `parent` | For sub-tasks | Parent issue key, e.g., `"PROJ-123"` | + +### Common mistakes to avoid + +- Do NOT use `parentKey` — the correct parameter is **`parent`** +- Do NOT use `projectIdOrKey` — the parameter is `projectKey` +- Do NOT use `issueTypeId` — the parameter is `issueTypeName` +- Do NOT omit `cloudId` — it is always required +- Do NOT guess issue type names — fetch them first with `getJiraProjectIssueTypesMetadata` +- Do NOT use a placeholder description and add content as a comment — put the full description in the `description` parameter when creating the issue + +### Recommended sequence for sub-task creation + +1. `getAccessibleAtlassianResources` → get `cloudId` +2. `getJiraProjectIssueTypesMetadata(cloudId, projectIdOrKey)` → get exact subtask type name +3. `createJiraIssue(cloudId, projectKey, issueTypeName, summary, description, parent)` → create the sub-task with full description + +Cache the `cloudId` and issue type names for the session — do not re-fetch them for each sub-task. + +## Fetching Jira Issues — Token-Efficient Extraction + +When fetching a ticket with `getJiraIssue`, the response contains extensive metadata (avatar URLs, status URLs, project metadata, user details). **Do not repeat the full response in conversation.** + +After fetching, immediately extract and summarize only these fields: +- **Summary** — issue title +- **Description** — ticket body (contains AC) +- **Status** — current status name +- **Issue type** — task, bug, story, etc. +- **Parent key** — if it's a sub-task + +Discard: avatar URLs, self links, status category metadata, project avatar URLs, user account IDs, timezone info, and other Atlassian infrastructure fields. + +Present the extracted information as a brief summary to the user, not as raw JSON. + +## Searching Jira Issues + +Use `mcp_atlassian_searchJiraIssuesUsingJql` with: + +| Parameter | Required | +|-----------|----------| +| `cloudId` | Yes | +| `jql` | Yes | + +Prefer a single broad JQL query over multiple narrow queries. Filter results in-memory rather than making separate API calls for each category. + +### Pagination + +The search tool returns a **limited number of results per call** (typically 10-25). If the total count exceeds the returned results, you MUST paginate to get all data. + +**Pagination technique:** Add `AND key < "{lastKeyFromPreviousPage}"` to the JQL to fetch the next page: + +1. First call: `project = PROJ AND type = Bug ORDER BY key DESC` +2. If result shows more items exist, note the last key returned (e.g., `PROJ-50`) +3. Next call: `project = PROJ AND type = Bug AND key < "PROJ-50" ORDER BY key DESC` +4. Repeat until no more results are returned + +**Always check if results are complete.** If the response indicates a `total` higher than the number of returned issues, paginate. Do NOT generate reports or analysis from partial data — fetch all pages first. + +### Setting `maxResults` for Reports and Bulk Analysis + +The default `maxResults` is **10**, which is insufficient for quality reports, dashboards, or any analysis that needs complete data. When fetching data for reports: + +- Set `maxResults: 50` (or up to `100`) for any query where you need all results +- If the `total` in the response exceeds `maxResults`, paginate immediately — do NOT proceed with partial data +- For quality health reports: always verify the returned count matches the `total` before generating visualizations + +### Include All Defect-Related Issue Types + +Projects often define multiple defect-tracking issue types beyond just `"Bug"`. Common patterns: + +- `Bug` — standalone defects (standard Jira type) +- `Story bug` — defects found during story implementation (subtask-level) +- `Defect`, `Production Bug`, etc. — project-specific types + +**Before generating quality reports:** +1. Check available issue types with `getJiraProjectIssueTypesMetadata` +2. Identify ALL defect-related types (look at `hierarchyLevel: 0` for standard and `hierarchyLevel: -1` for subtask types) +3. Include all of them in the JQL: `type in (Bug, "Story bug")` — not just `type = Bug` + +**Common mistake:** Querying only `type = Bug` and missing subtask-level defects like `"Story bug"`. This produces incomplete reports that undercount defects significantly. + +## Constructing Jira URLs for Links + +When generating reports (HTML, Confluence, Jira ticket descriptions), always link to Jira rather than showing plain text. Derive the base URL from the `getAccessibleAtlassianResources` response (the `url` field, e.g., `https://your-instance.atlassian.net`). + +| Link target | URL pattern | +|-------------|-------------| +| Single issue | `{baseUrl}/browse/{issueKey}` | +| Project board | `{baseUrl}/jira/software/projects/{projectKey}/board` | +| JQL filter (issue navigator) | `{baseUrl}/issues/?jql={urlEncodedJql}` | + +**In HTML reports:** +- KPI card values (open bugs count, total count, etc.) → wrap in `` linking to the JQL filter that produces that count. +- Bug keys in tables → link to `{baseUrl}/browse/{key}`. +- JQL query shown in methodology → render as clickable link to the issue navigator. +- Project name in header → link to the project board. + +## Editing Jira Issues + +Use `mcp_atlassian_editJiraIssue` to update an existing issue's fields (e.g., description): + +| Parameter | Required | +|-----------|----------| +| `cloudId` | Yes | +| `issueIdOrKey` | Yes | +| `description` | No — field to update | +| `summary` | No — field to update | + +## Adding Comments to Jira Issues + +Use `mcp_atlassian_addCommentToJiraIssue` with: + +| Parameter | Required | +|-----------|----------| +| `cloudId` | Yes | +| `issueIdOrKey` | Yes | +| `commentBody` | Yes | + +## Confluence — Creating Pages + +Use `mcp_atlassian_createConfluencePage` with these **exact parameter names**: + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `cloudId` | Yes | From `getAccessibleAtlassianResources` | +| `spaceId` | Yes | **Numeric** space ID (e.g., `"1234567890"`). NOT the space key. | +| `parentId` | No | Numeric page ID of the parent page (for subpages) | +| `title` | Yes | Page title | +| `body` | Yes | Page body in **ADF JSON** format (not markdown, not storage/XHTML) | + +### Handling the creation response — Extracting the page URL + +The `createConfluencePage` response is often large and written to a file. You **MUST** read that file to extract the correct `id` field before presenting a link to the user. + +**Correct URL construction after creation:** +``` +1. Read the response file returned by the tool +2. Extract the `id` field (e.g., "6113361923") +3. Extract the `_links.webui` field (e.g., "/spaces/Hiber/pages/6113361923/My+Page") +4. Construct the full URL: https://{instance}.atlassian.net/wiki{webui} +``` + +**Common mistake:** Guessing or fabricating the page ID without reading the creation response. This produces broken links. NEVER assume a page ID — always read it from the API response. + +### Common mistakes to avoid + +- Do NOT use the space **key** (e.g., `"MYSPACE"`) as `spaceId` — it must be a **numeric** ID +- Do NOT use markdown or XHTML for `body` — Confluence Cloud API requires **ADF (Atlassian Document Format)** JSON +- Do NOT skip `parentId` when creating subpages — without it the page lands at the space root +- Do NOT guess page IDs for confirmation links — always extract from the creation response + +### Resolving a Confluence Space's Numeric `spaceId` + +`getConfluenceSpaces` returns only the first 25 spaces with **no pagination support**. If the target space is not in the first batch, you cannot page through results. + +**Primary method — resolve via `getConfluencePage`:** + +1. Obtain the ID of **any page** in the target space (from a URL the user provides, or from a `searchConfluenceUsingCql` result) +2. Call `getConfluencePage(cloudId, pageId)` — the response **directly includes `spaceId`** as a top-level field +3. Use that `spaceId` for all subsequent page creation/update calls + +This is the simplest and most reliable approach. + +**Fallback — resolve via ARI fetch** (only if `getConfluencePage` does not return `spaceId` for some reason): + +1. Call `mcp_atlassian_fetch(url: "ari:cloud:confluence:{cloudId}:page/{pageId}")` +2. The response includes `metadata.spaceId` + +Cache the resolved `spaceId` for the session — do not re-fetch it for each page creation. + +### Extracting Page IDs from Confluence URLs + +When a user provides a Confluence URL, extract the **numeric page ID** from it: + +``` +https://{instance}.atlassian.net/wiki/spaces/{spaceKey}/pages/{pageId}/{title} +``` + +Example: `https://your-instance.atlassian.net/wiki/spaces/MYSPACE/pages/1234567890/My+Page` +→ pageId = `1234567890` + +Use the extracted `pageId` as: +- `parentId` when creating subpages +- Input for `getConfluencePage` to resolve `spaceId` +- `pageId` when fetching or updating pages + +### Recommended sequence for Confluence page creation + +1. `getAccessibleAtlassianResources` → get `cloudId` +2. Get page ID using **one of**: + - **User provides a URL** → extract `pageId` from the path (`/pages/{pageId}/`) + - **User provides space name + page title** → use `searchConfluenceUsingCql(cloudId, cql: 'space = "{spaceKey}" AND title = "{pageTitle}"')` → extract `pageId` from the result +3. `getConfluencePage(cloudId, pageId)` → read `spaceId` from the response +4. Use the `pageId` as `parentId` for subpages +5. `createConfluencePage(cloudId, spaceId, parentId, title, body)` → create the page with full ADF body + +The user should never need to provide numeric IDs — they provide human-readable identifiers (URL, space name, page title) and the agent resolves the rest. + +## Confluence — Updating Pages + +Use `mcp_atlassian_updateConfluencePage` with: + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `cloudId` | Yes | From `getAccessibleAtlassianResources` | +| `pageId` | Yes | Numeric page ID to update | +| `title` | Yes | Page title (can be same as existing) | +| `body` | Yes | Full page body in **ADF JSON** format (replaces existing content) | +| `version` | Yes | New version number (current version + 1). Fetch current version first with `getConfluencePage`. | + +### Common mistakes to avoid + +- Do NOT omit `version` — the API requires an incremented version number +- The `body` replaces the entire page content — there is no append/patch mode + +## Confluence — Fetching Pages + +Use `mcp_atlassian_getConfluencePage` with: + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `cloudId` | Yes | From `getAccessibleAtlassianResources` | +| `pageId` | Yes | Numeric page ID | + +Returns page title, body (in ADF or storage format), version number, and metadata. + +## Confluence — Searching with CQL + +Use `mcp_atlassian_searchConfluenceUsingCql` with: + +| Parameter | Required | Description | +|-----------|----------|-------------| +| `cloudId` | Yes | From `getAccessibleAtlassianResources` | +| `cql` | Yes | Confluence Query Language string | + +Useful CQL patterns: +- `space = "MYSPACE" AND title = "Regression"` — find pages by title in a space +- `space = "MYSPACE" AND ancestor = 1234567890` — find all descendants of a page +- `space = "MYSPACE" AND type = page AND label = "qa"` — find pages with a label + +Note: CQL uses the **space key** (e.g., `"MYSPACE"`) — this is one of the few places where the space key (not numeric ID) is correct. + +## Format Differences — Jira vs Confluence + +| Tool | Body format | +|------|-------------| +| `createJiraIssue` — `description` | **Markdown** | +| `addCommentToJiraIssue` — `commentBody` | **Markdown** | +| `editJiraIssue` — `description` | **Markdown** | +| `createConfluencePage` — `body` | **ADF JSON** | +| `updateConfluencePage` — `body` | **ADF JSON** | + +Do NOT mix these up. Jira accepts markdown strings. Confluence requires valid ADF (Atlassian Document Format) JSON with `{"type":"doc","version":1,"content":[...]}` structure. diff --git a/.github/internal-prompts/tsh-implement-e2e.prompt.md b/.github/internal-prompts/tsh-implement-e2e.prompt.md index 02818868..b3ed1ac8 100644 --- a/.github/internal-prompts/tsh-implement-e2e.prompt.md +++ b/.github/internal-prompts/tsh-implement-e2e.prompt.md @@ -1,5 +1,5 @@ --- -agent: "tsh-e2e-engineer" +agent: "tsh-qa-engineer" model: "Claude Opus 4.6" description: "Create, maintain, and execute E2E tests for given feature or user story." --- diff --git a/.github/internal-prompts/tsh-report-bug.prompt.md b/.github/internal-prompts/tsh-report-bug.prompt.md new file mode 100644 index 00000000..88780248 --- /dev/null +++ b/.github/internal-prompts/tsh-report-bug.prompt.md @@ -0,0 +1,27 @@ +--- +agent: "tsh-qa-engineer" +model: "Claude Opus 4.6" +description: "Create a professional bug report with severity classification, steps to reproduce, and structured formatting." +argument-hint: "[Bug description or observed behavior]" +--- + +Create a professional, structured bug report from the provided bug description or observed behavior. The report follows the standard bug report template with severity classification, clear reproduction steps, and expected vs actual behavior. + +## Required Skills + +Before starting, load and follow these skills: +- `tsh-functional-testing` - provides the severity matrix and bug report template + +## Workflow + +1. Gather bug details from the user's description +2. Structure the report following the `bug-report.example.md` template from `tsh-functional-testing`, classifying severity using the skill's severity matrix +3. Review completeness — verify the report contains enough detail for a developer to reproduce the issue without additional context +4. Present the bug report in the conversation + +## Constraints + +- Every bug report must include numbered Steps to Reproduce — vague descriptions like "it doesn't work" are not acceptable. +- Severity must be classified using the severity matrix (Critical / High / Medium / Low) with justification. +- Do not speculate on root cause unless evidence is clear — focus on observable behavior. +- If the user provides insufficient information to write a complete report, ask for the missing details before generating. diff --git a/.github/prompts/tsh-analyze-materials.prompt.md b/.github/prompts/tsh-analyze-materials.prompt.md index 0012dc8a..29c2cafb 100644 --- a/.github/prompts/tsh-analyze-materials.prompt.md +++ b/.github/prompts/tsh-analyze-materials.prompt.md @@ -49,5 +49,6 @@ Determine the entry point based on what the user provides: - When working with imported Jira tasks, the quality review step still applies — it can identify gaps in existing backlogs just as with newly extracted tasks. - After import or initial creation, individual task changes trigger a "Push to Jira now?" prompt. Batch pushes follow the standard Gate 2 approval. - If no transcript is provided (e.g., user provides structured notes or direct requirements), skip the transcript processing step and proceed directly to task extraction. +- **AC readiness for QA**: Ensure all acceptance criteria are test-ready before the workflow completes. Test-ready AC define clear expected outcomes, identifiable preconditions, and explicit boundaries per user-facing behavior. If QA redirects a task back due to incomplete AC, use `tsh-task-analysing` (Step 3b) to resolve the gaps. Follow the template structures and naming conventions from each skill strictly to ensure clarity and consistency. diff --git a/.github/prompts/tsh-qa-workflow.prompt.md b/.github/prompts/tsh-qa-workflow.prompt.md new file mode 100644 index 00000000..27d749c5 --- /dev/null +++ b/.github/prompts/tsh-qa-workflow.prompt.md @@ -0,0 +1,127 @@ +--- +agent: "tsh-qa-engineer" +model: "Claude Opus 4.6" +description: "Single QA entrypoint — runs the full workflow or jumps to a specific flow (report bug, plan testing, regression, etc.) based on context." +argument-hint: "[flow: report bug | plan testing | test cases | regression | test report | quality health] + [Jira ticket ID, feature description, or acceptance criteria]" +--- + + +Single entrypoint for all QA work. Routes to the correct flow based on the user's context: +- If the argument specifies a flow (e.g., "report bug", "plan regression"), jump directly to that flow (quick mode). +- If no specific flow is mentioned, run the full sequential workflow with checkpoints. + + +## Quick-Flow Routing + +Parse the user's argument for these keywords and route directly: + +| Keyword in argument | Jumps to | Skill / Template | +|---|---|---| +| `report bug` / `bug` | Bug Report | `tsh-functional-testing` (severity matrix + `bug-report.example.md`) | +| `plan testing` / `test plan` | Phase 1 only | `tsh-planning-tests` | +| `test cases` | Phase 2 only | `tsh-planning-tests` | +| `regression` | Phase 3 only | `tsh-analyzing-regression-risk` | +| `test report` | Phase 4 only | `tsh-functional-testing` (`test-report.example.md`) | +| `quality health` / `quality report` | Phase 5 only | `tsh-analyzing-bugs` | +| `audit accessibility` / `a11y` | Accessibility Audit | `tsh-accessibility-auditing` | +| `verify ac` | AC Verification | `tsh-verifying-acceptance-criteria` | +| `generate test data` / `test data` | Test Data Generation | `tsh-generating-test-data` | + +**Quick-flow behavior**: Skip Phase 0 kickoff questions. Ask only what the specific flow needs (e.g., delivery destination). Execute that single flow and stop — do not continue to the next phase. + +**Full workflow** (no keyword match): Run all phases sequentially as described below. + +## Phases + +| # | Phase | Skill | Output | +|---|-------|-------|--------| +| 0 | Kickoff | — | Validate AC, ask delivery destination | +| 1 | Plan Testing | `tsh-planning-tests` | Test plan | +| 2 | Create Test Cases | `tsh-planning-tests` | Executable test cases | +| 3 | Plan Regression | `tsh-analyzing-regression-risk` | Regression scope + test suite | +| 4 | Create Test Report | `tsh-functional-testing` (template) | Go/No-Go verdict | +| 5 | Quality Health Report | `tsh-analyzing-bugs` | Quality dashboard | + +**Side-flows** (available at any checkpoint): Report a Bug, Audit Accessibility, Verify AC, Generate Test Data. + +## How It Works + +1. **Phase 0 — Kickoff** (silent, no chat output) + - Accept input (Jira ticket ID or description). If Jira, fetch ticket silently. + - Validate AC completeness gate. If gaps found → redirect to `/tsh-analyze-materials`. Stop. + - Ask delivery destination + API testing relevance in one `vscode/askQuestions` call. + +2. **Phase 1 — Plan Testing** + - Load and follow `tsh-planning-tests` skill workflow. + - Deliver to chosen destination. Checkpoint: continue / skip ahead. + +3. **Phase 2 — Create Test Cases** + - Generate test cases from the plan using `test-cases.example.md` template. + - Deliver to chosen destination. Checkpoint: continue / skip. + +4. **Phase 3 — Plan Regression** + - Ask in one `vscode/askQuestions` call (in this order): delivery destination, then regression scope (current task / current sprint / date range). + - Load and follow `tsh-analyzing-regression-risk` skill workflow. + - Deliver regression test suite. Checkpoint: continue / skip. + +5. **Phase 4 — Create Test Report** + - Ask delivery destination + test results source. + - Generate report using `test-report.example.md`. Include Go/No-Go verdict. + - Deliver. Checkpoint: continue / done. + +6. **Phase 5 — Quality Health Report** + - Load `tsh-analyzing-bugs` skill. Ask scope + delivery destination. + - Follow the skill's full workflow (handles JQL, pagination, analysis, charting). + - Deliver. Final checkpoint: re-run a phase / done. + +## Checkpoint Pattern + +After each phase delivers its artifact, present options via `vscode/askQuestions`: +- Phase-specific next step (recommended) +- Skip ahead to a later phase +- Branch: "Report a Bug" / "Audit Accessibility" +- "Stop here" + +## Side-flows + +| Action | Delegates to | +|--------|-------------| +| Report a Bug | `bug-report.example.md` + severity matrix from `tsh-functional-testing` | +| Audit Accessibility | `tsh-accessibility-auditing` skill (load on demand) | +| Verify AC | `tsh-verifying-acceptance-criteria` skill | +| Generate Test Data | `tsh-generating-test-data` skill | + +After any side-flow completes, return to the triggering checkpoint. + +## Delivery Behavior + +**Existing Jira ticket as destination**: When the user provides an existing Jira ticket (e.g., a link or key like `PROJ-123`) as the delivery destination, **always ask** whether the artifact should be delivered as: +- The ticket's **description** (replaces existing description), OR +- A **comment** on the ticket (appends without overwriting) + +Do not assume one or the other — ask explicitly via `vscode/askQuestions` before delivering. + +When the user selects a **non-chat destination** (Jira sub-task, Jira comment, Confluence page, local file): +1. Generate the artifact content internally — do NOT render it in chat. +2. Deliver directly to the chosen destination using the appropriate tool. +3. After delivery, **read the tool response** to extract the exact ID (page ID, issue key). +4. Construct the confirmation link from the **actual response ID** — never guess or fabricate IDs. +5. Confirm delivery with **only** the ticket key/page title + correct link. No content echo. + +**Phase 2 follows Phase 1's sub-task**: When delivery destination is "Jira sub-task", Phase 1 creates the sub-task (test plan) and Phase 2 delivers the test cases as a **comment on the Phase 1 sub-task** — not as a separate sub-task. This keeps the test plan and its derived test cases together on one ticket. + +When a skill instructs "present the output first" (e.g., `tsh-planning-tests` Step 2 says "Present only the test plan first"), this applies **only when delivery destination is chat**. For all other destinations, deliver directly without presenting in chat. + +**Do not re-ask the delivery destination** after the user has already answered. The answer from Phase 0 (or the phase-specific question for Phases 3–5) is final — act on it immediately. + +## Constraints + +- **Phase 0 must be silent** — no chat output until kickoff questions or AC-gap list. +- Do not skip the AC Completeness Gate. +- Do not fabricate test results in Phase 4. +- Delivery destination from Phase 0 applies to Phases 1–2 only. Phases 3–5 ask their own. +- **Never echo artifact content into chat when destination is Jira or Confluence.** Confirm with ticket key + link only. +- **Never re-ask a question the user already answered.** If the destination was chosen, deliver there without further confirmation. +- Load skills lazily — only when their phase is reached. +- Follow `tsh-atlassian-mcp` instruction file for Jira/Confluence tool patterns. +- Cache `cloudId` and issue type metadata for the session — do not re-fetch per call. diff --git a/.github/skills/tsh-accessibility-auditing/SKILL.md b/.github/skills/tsh-accessibility-auditing/SKILL.md new file mode 100644 index 00000000..05663cc0 --- /dev/null +++ b/.github/skills/tsh-accessibility-auditing/SKILL.md @@ -0,0 +1,330 @@ +--- +name: tsh-accessibility-auditing +description: "WCAG 2.2 Level AA accessibility auditing using POUR methodology, automated tools, and manual testing checklists. Generates technical audit reports and business-facing summaries. Use when conducting accessibility audits on URLs or codebases, producing audit reports, generating business summaries, or checking WCAG compliance." +--- + +# Accessibility Auditing + +Conducts WCAG 2.2 Level AA accessibility audits using a hybrid approach of automated tools and manual testing, following the POUR (Perceivable, Operable, Understandable, Robust) methodology. + +## Knowledge Base & Standards + +Audits are strictly based on: +1. **W3C WCAG 2.2 Guidelines** (https://www.w3.org/WAI/standards-guidelines/wcag/) +2. **Polska Ustawa o dostępności cyfrowej** (https://orka.sejm.gov.pl/proc10.nsf/ustawy/241_u.html) +3. **LepszyWeb WCAG Guide** (https://wcag.lepszyweb.pl/) + +**IMPORTANT**: WCAG 2.2 removed SC 4.1.1 Parsing. Do not report 4.1.1 violations. + +## Audit Process + +Use the checklist below and track your progress: + +``` +Progress: +- [ ] Step 1: Detect audit mode +- [ ] Step 2: Run automated tools +- [ ] Step 3: Perform manual testing +- [ ] Step 4: Check WCAG 2.2 new criteria +- [ ] Step 5: Classify and de-duplicate findings +- [ ] Step 6: Generate audit report +``` + +**Step 1: Detect audit mode** + +Determine the audit type: +- **External Audit** (URL provided, no code access): Use `execute` tool to run CLI tools against the URL. Fetch page HTML for manual analysis. +- **Internal Audit** (codebase access): Use `read` and `search` tools to inspect source files. Run CLI tools against local dev server if available. + +**IMPORTANT**: For browser-based verification (keyboard navigation, focus order, page state capture), prefer the VS Code built-in browser tools (`open_browser_page`, `click_element`, etc.) over Playwright MCP. These are lighter-weight, require no user permission, and work inline within the editor. Only fall back to Playwright MCP if the built-in browser is insufficient (e.g., complex multi-tab flows). + +**Step 2: Run automated tools** + +**Tool selection**: Run all tools by default for comprehensive coverage. If the user explicitly names specific tools in their request (e.g. "scan with achecker", "use pa11y and axe only"), run **only** those tools and note in the report that coverage may be partial since no single tool catches more than ~30-40% of issues. + +Available tools: +| Tool | Command | +|---|---| +| pa11y | `pa11y --reporter cli --standard WCAG2AA` | +| axe-core | `axe --tags wcag2a,wcag2aa` | +| Lighthouse | `lighthouse --only-categories=accessibility --output=cli --chrome-flags="--headless --no-sandbox"` | +| IBM Equal Access | `achecker ` | +| html-validate | `curl -s \| html-validate --stdin` | + +See `./references/automated-tools.md` for full usage examples. + +If tools are not installed, run: `npm install -g pa11y @axe-core/cli lighthouse html-validate accessibility-checker` + +**Step 3: Perform manual testing** + +Automated tools miss 60-70% of accessibility issues. Supplement with manual checks: + +### Keyboard Navigation +- Tab through the entire page — every interactive element must be reachable +- Focus order must follow visual/reading flow +- Focus indicator must always be visible +- Modals must be closable with Escape and trap focus internally +- No keyboard traps — user can always move forward and backward +- Skip-to-main-content link must be present and functional + +### Screen Reader +- All images have appropriate alt text (informative or `alt=""` for decorative) +- Form fields have accessible names (visible labels or `aria-label`) +- Dynamic content changes are announced (`aria-live`, `role="alert"`) +- Landmark regions present (`
`, `