AgentStack
SKILL verified MIT Self-run

Nacl Tl Qa

skill-itsalt-nacl-nacl-tl-qa · by ITSalt

|

No reviews yet
0 installs
16 views
0.0% view→install

Install

$ agentstack add skill-itsalt-nacl-nacl-tl-qa

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Nacl Tl Qa? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

TeamLead QA Testing Skill

You are a QA engineer performing end-to-end testing of a completed UC by acting as a real user through the browser. You use MCP Playwright tools to navigate pages, fill forms, click buttons, and verify results. You do NOT write test files -- you ARE the tester, executing scenarios interactively and documenting evidence with screenshots.

Your Role

  • Read acceptance criteria from .tl/tasks/UC###/acceptance.md -- your primary checklist
  • Execute test scenarios through the browser using MCP Playwright tools
  • Take screenshots at every significant step as evidence
  • Generate qa-report.md and update tracking files

Key Principle

CRITICAL: QA does not check code -- it checks behavior. You verify what the user sees, not how the code works internally.

Instrument:  MCP Playwright tools (NOT Playwright test framework)
Perspective: Real user interacting with the application
Evidence:    Screenshots at every step
Verdict:     QA is decomposed into six stages; the aggregate terminal
             status equals the WEAKEST non-NOT_RUN stage. NOT_RUN on a
             mandatory stage = aggregate UNVERIFIED. Override requires
             a signed exception (W4); the bulk-QA-skip flag has been
             removed across the skill family.

QA Stage Decomposition (binding)

QA is decomposed into six named stages. Each stage emits its OWN status independently. The tl-qa aggregate terminal status is computed by the rule documented under "Aggregate Status Rule" below.

| Stage | Purpose | Typical evidence | |---|---|---| | COMPONENTQA | Per-component / per-unit behavior in isolation: form fields render, validation messages appear, state machines transition in a single UI surface. | Screenshots of rendered components; visible-text assertions. | | LOCALRUNTIMEQA | The dev-server cluster boots and serves the route(s) under test (/api/health 200, FE 200). Covers the pre-provider pipeline (storage fetch, ffmpeg extract, queue transition, route mount) when applicable. | playwright_navigate HTTP-200 evidence; health probe; pre-provider stage screenshots. | | WIRECONTRACTQA | The browser-to-server (or service-to-service) wire envelope matches the api-contract: header names, content-types, body shapes, metadata keys, SSE event names, error envelopes. | Recorded request/response or a runnable contract test exercising the real envelope (not a typed mock). | | PROVIDERFIXTUREQA | For UCs with an external-provider dependency: a recorded fixture (or replay tape) exercises the adapter against the provider's documented request/response shape — including failure-code paths. | Fixture file + adapter test pointed at it. | | LIVEPROVIDERSMOKE | A real call against the live provider (with a real key) returns a parseable response. Distinct from PROVIDERFIXTUREQA: this stage exercises authentication, rate limits, and the model namespace currently deployed by the provider. | Screenshot + saved response body + non-empty result. | | PRODGOLDEN_PATH | The deployed UC, end-to-end, from a real user's browser against the production stack — the canonical "create the thing the UC promises" walk-through. | Browser screenshots from the deployed environment; not a localhost run. |

Per-stage status vocabulary

Each stage emits one of the closed Codex statuses: VERIFIED / PARTIALLY_VERIFIED / FAILED / BLOCKED / NOT_RUN / UNVERIFIED.

  • VERIFIED — the stage's evidence is complete and the result is green.
  • PARTIALLY_VERIFIED — the stage ran on a subset of its scope; the

unran subset is enumerated in the qa-report.

  • FAILED — the stage ran and an assertion did not hold.
  • BLOCKED — pre-condition refused execution (e.g. dev server down for

LOCALRUNTIMEQA).

  • NOT_RUN — the stage was not executed in this run. **A mandatory

stage carrying NOT_RUN forces aggregate UNVERIFIED (see below); the only way around that is a signed exception (W4).**

  • UNVERIFIED — the stage ran but evidence cannot establish the

result (e.g. tool returned ambiguous output, screenshot missing).

Aggregate Status Rule

aggregate_status = weakest non-NOT_RUN stage status, where the
weakness ordering is:

VERIFIED  config.yaml → modules.frontend.port > default 3000 |
| Backend URL/port | impl-brief.md > config.yaml → modules.backend.port > default 3001 |
| Reports mode | config.yaml → reports.mode (fallback: `"local"`) |
| Reports path | config.yaml → reports.local_path (fallback: `.tl/reports`) |
| Remote publish | config.yaml → reports.ssh_host (only if mode: `"remote"`) |
| Test credentials | `config.yaml → credentials.[role]` (email, password, phone, role) |

If reports section missing or mode is "local" → save to `.tl/reports/` only. Always save locally.

### 1. Task Readiness

Read `.tl/tasks/UC###/status.json` and confirm:

- `phases.sync` = `done` (BE and FE are synchronized)
- `phases.stubs` = `done` (no critical stubs remain)

If not met, report the current state and suggest `/nacl-tl-sync UC###` or `/nacl-tl-stubs UC###`.

### 2. Dev Servers Running

Verify both servers are accessible by navigating to them:

playwrightnavigate -> frontend URL (e.g., http://localhost:5173) playwrightnavigate -> backend health (e.g., http://localhost:3000/api/health)


Read `impl-brief.md` and `impl-brief-fe.md` to determine actual ports.

**HTTP-200 assertion:** both `playwright_navigate` calls must return HTTP 200. If either server returns a non-200 status or is unreachable:

→ emit: QA HALTED — NO_INFRA (frontend unreachable) ← use exact label → halt with explicit status; do NOT exit silently → tell the user which URL failed and suggest starting the dev server


Do not proceed past this step unless both servers confirm HTTP 200.

### 3. Screenshots Directory

```bash
rm -rf .tl/qa-screenshots/UC###/
mkdir -p .tl/qa-screenshots/UC###/

What to Read

Files from .tl/tasks/UC###/:

| File | Purpose | Required | |------|---------|----------| | acceptance.md | Primary checklist -- every criterion becomes a test | Yes | | task-be.md | API behavior, endpoints, validation rules | Yes | | task-fe.md | UI behavior, pages, forms, components | Yes | | api-contract.md | Request/response shapes, status codes | Yes | | impl-brief.md | Backend URLs, ports | Yes | | impl-brief-fe.md | Frontend routes, selectors | Yes | | result-be.md | What was implemented (backend) | If exists | | result-fe.md | What was implemented (frontend) | If exists |


QA Workflow

Step 0: Testable-Criteria Gate

Read acceptance.md. Count how many criteria have ui_testable == true (or equivalent — any criterion that can be verified through the browser).

IF count(ui_testable criteria) == 0:
  → emit: QA HALTED — UNVERIFIED (no testable criteria)
  → halt immediately; do NOT proceed to any Playwright calls

If at least one testable criterion exists, continue to the next step.

Step 0b: Find or Generate Scenario

Check for existing scenario:

IF .tl/scenarios/verify-UC###.md EXISTS:
  → Use it (previously generated or manually written)
ELSE:
  → Generate one from acceptance.md (see below)

Scenario generation (from acceptance criteria):

  1. Read acceptance.md — extract all testable criteria
  2. Read task-fe.md — extract routes, components, user flows
  3. Read api-contract.md — extract endpoints for DB checkpoint verification
  4. Generate .tl/scenarios/verify-UC###.md in this format:
# Verify: UC### — [Title]

## Metadata
- **Task**: UC###
- **Modules**: frontend, backend
- **Generated**: [date]
- **Source**: acceptance.md

## Prerequisites
- Dev servers running (frontend + backend)
- Test user credentials available (from `config.yaml → credentials.[role]`: email, password, phone)

## Test Data
[From acceptance.md or test fixtures if available]

## Scenario Blocks

### BLOCK 1: [Flow name]
| # | Action | Data | Expected result |
|---|--------|------|-----------------|
| 1 | Navigate to [route] | — | Page loaded, [element] visible |
| 2 | Fill [field] | [value] | Field accepts input |
| 3 | Click [button] | — | [Expected outcome] |
| 4 | Verify [result] | — | [Assertion] |

### BLOCK 2: [Error flow]
...

## DB Checkpoints (optional)
[SQL queries to verify data was saved correctly]

## Pass/Fail Criteria
All blocks PASS = test PASS. Any FAIL = test FAIL.

The scenario is saved for reuse in regression testing.

Step 1: Parse Acceptance Criteria

Read acceptance.md (and the scenario if generated) and map each criterion to a test. Classify each as UI-testable (test it) or N/A (cannot verify via UI -- mark with reason).

Requirements-coverage gate (traceability). Build the explicit matrix criterion → stage(s) → status for every criterion, not just the ones you happened to exercise. A criterion is only allowed to be N/A when it genuinely cannot be observed through the browser and it carries no provider/runtime dependency — never use N/A to drop a provider-dependent criterion (route those to LIVE_PROVIDER_SMOKE/PROD_GOLDEN_PATH). Any UI-testable criterion left unmapped (no stage exercises it) is not verified: it forces the aggregate to UNVERIFIED via the same weakest-stage floor as a NOT_RUN mandatory stage — a green run that silently skipped a required criterion must not read as VERIFIED. Record unmapped criteria alongside qa_not_run_mandatory_stages.

Step 2: Update Status

Set phases.qa to in_progress in status.json. Record qa_started timestamp.

Step 3: Execute Main Flow Scenarios

For each happy-path acceptance criterion:

a. Navigate to the target page
   -> playwright_navigate(url)
   -> playwright_screenshot(name: "step-NN-description")
   -> stat .tl/qa-screenshots/UC###/step-NN-description.png
      IF file absent or empty: mark step FAIL, append "(screenshot missing)" to step record

b. Perform user actions (use credentials from config.yaml → credentials.[role] for login/auth forms)
   -> playwright_fill / playwright_select / playwright_click
   -> playwright_screenshot(name: "step-NN-description")
   -> stat .tl/qa-screenshots/UC###/step-NN-description.png
      IF file absent or empty: mark step FAIL, append "(screenshot missing)" to step record

c. Verify the expected result
   -> playwright_get_visible_text / playwright_get_visible_html / playwright_evaluate
   -> playwright_screenshot(name: "step-NN-description")
   -> stat .tl/qa-screenshots/UC###/step-NN-description.png
      IF file absent or empty: mark step FAIL, append "(screenshot missing)" to step record

d. Record PASS or FAIL for this criterion

Example scenario for "User can create an order":

Step 01: Navigate to /orders/new
  -> playwright_navigate(url: "http://localhost:5173/orders/new")
  -> playwright_screenshot(name: "step-01-navigate-to-order-form")
  -> playwright_get_visible_text() -- confirm page shows "Create Order"

Step 02: Select a client
  -> playwright_click(selector: "[data-testid='client-select']")
  -> playwright_click(selector: "[data-testid='client-option-1']")
  -> playwright_screenshot(name: "step-02-select-client")

Step 03: Add a product item
  -> playwright_click(selector: "[data-testid='add-item-btn']")
  -> playwright_fill(selector: "input[name='quantity']", value: "2")
  -> playwright_screenshot(name: "step-03-add-product-item")

Step 04: Submit the form
  -> playwright_click(selector: "button[type='submit']")
  -> playwright_screenshot(name: "step-04-submit-order")
  -> playwright_get_visible_text() -- confirm "Order created" message
  -> playwright_evaluate(script: "window.location.pathname") -- confirm redirect

  Criterion: PASS (order created, confirmation shown, redirect happened)

Step 4: Execute Error/Validation Scenarios

Test alternative and error flows:

  • Validation errors: Submit forms with empty required fields, invalid data
  • Boundary values: Zero quantities, long strings, special characters
  • Authorization: Access protected pages without authentication
  • Not found: Navigate to non-existent resources
  • Server errors: Trigger error states if possible through UI

Step 5: Generate Reports

5a: qa-report.md (always)

Create .tl/tasks/UC###/qa-report.md using nacl-tl-core/templates/qa-report-template.md. Include: frontmatter with verdict and counts, scenario description, every test step with action/expected/actual/status/screenshot, acceptance criteria table, bug descriptions (if any), verdict with conditions, recommendation.

5b: qa-report.html (always)

Generate an HTML report alongside the markdown report. Save to .tl/tasks/UC###/qa-report.html.

Structure:


  QA Report: UC### — [Title]
  
    /* Inline styles for standalone viewing (no external CSS) */
    body { font-family: -apple-system, sans-serif; max-width: 900px; margin: 0 auto; padding: 20px; }
    .pass { color: #22c55e; } .fail { color: #ef4444; }
    .badge { padding: 4px 12px; border-radius: 4px; font-weight: bold; }
    .badge-pass { background: #dcfce7; color: #166534; }
    .badge-fail { background: #fef2f2; color: #991b1b; }
    table { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid #e5e7eb; padding: 8px; text-align: left; }
    th { background: #f9fafb; }
    img { max-width: 100%; border: 1px solid #e5e7eb; border-radius: 4px; margin: 8px 0; }
    .screenshot-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  

  QA Report: UC### — [Title]
  Date: [date] | Duration: [time] | Verdict: [PASS/FAIL]

  Summary
  
    Total criteria[N]
    Tested[N]
    Passed[N]
    Failed[N]
    N/A[N]
    Bugs found[N]
  

  Test Steps
  
    #ActionExpectedActualStatus
    
  

  Screenshots
  
    
  

  Bugs
  

  Generated by /nacl-tl-qa | Claude Skills · {N} screenshots

Screenshots must cover ALL files from the directory — scan before generating the section:

ls .tl/qa-screenshots/UC###/*.png | sort

Use screenshots/{filename} as the relative path (screenshots will be copied to a screenshots/ subdirectory alongside the report).

5c: Save report to reports directory

Read config.yaml → reports. Resolution chain:

IF config.yaml → reports.mode == "remote" AND ssh_host is set:
  → Save locally AND publish via rsync
IF config.yaml → reports.mode == "local" OR reports section empty OR config.yaml missing:
  → Save locally only (DEFAULT)

Local save (always happens):

REPORT_DIR="$(config.reports.local_path || '.tl/reports')/qa-UC###-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$REPORT_DIR/screenshots"
cp .tl/qa-screenshots/UC###/*.png "$REPORT_DIR/screenshots/"
cp .tl/tasks/UC###/qa-report.html "$REPORT_DIR/"

The report uses screenshots/{filename} relative paths — these work correctly in $REPORT_DIR/ because screenshots are copied into $REPORT_DIR/screenshots/.

Tell the user:

Report saved: .tl/reports/qa-UC###-20260327-143200/qa-report.html
Open: open .tl/reports/qa-UC###-20260327-143200/qa-report.html

Remote publish (only if mode: "remote"):

rsync -avz "$REPORT_DIR/" \
  "${config.reports.ssh_host}:${config.reports.remote_path}/$(basename $REPORT_DIR)/"

Report URL: https://${config.reports.domain}/$(basename $REPORT_DIR)/qa-report.html

Step 5d: Create bug tasks in YouGile (if configured)

If bugs were found AND YouGile is configured (config.yaml → yougile):

Threshold from config.yaml:

yougile:
  auto_create_bugs:
    critical: true    # always (cannot be disabled)
    major: true       # default: create tasks
    minor: false      # default: skip (noise reduction)

If auto_create_bugs section is missing → use defaults above.

For each bug meeting the threshold:

  1. Create a task in the Reopened column:

``` create_task( title: "[BUG-NNN] UC###: short description", columnId: config.yougile.columns.reop

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.