synapse-hub 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents/failure-analyst.md +47 -0
- package/.agents/agents/live-explorer.md +41 -0
- package/.agents/agents/orchestrator.md +43 -0
- package/.agents/agents/pom-crafter.md +81 -0
- package/.agents/agents/quality-gatekeeper.md +47 -0
- package/.agents/agents/test-runner.md +43 -0
- package/.agents/rules/context-engineering.md +88 -0
- package/.agents/rules/git-push-protocol.md +101 -0
- package/.agents/rules/graphify.md +14 -0
- package/.agents/rules/lessons-learned.md +23 -0
- package/.agents/rules/mandatory-playwright-live.md +29 -0
- package/.agents/rules/skill-precedence.md +42 -0
- package/.agents/rules/systematic-debugging.md +99 -0
- package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +239 -0
- package/.agents/skills/antigravity-test-sentinel/SKILL.md +64 -0
- package/.agents/skills/api-network-mocking-interception/SKILL.md +142 -0
- package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +70 -0
- package/.agents/skills/architecture-decision-records/SKILL.md +441 -0
- package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +72 -0
- package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +214 -0
- package/.agents/skills/bats-testing-patterns/SKILL.md +100 -0
- package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -0
- package/.agents/skills/clean-pom-crafter/SKILL.md +75 -0
- package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -0
- package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -0
- package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +64 -0
- package/.agents/skills/code-refactoring-refactor-clean/resources/implementation-playbook.md +879 -0
- package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +123 -0
- package/.agents/skills/e2e-testing-patterns/SKILL.md +103 -0
- package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -0
- package/.agents/skills/failure-autopsy-and-healing/SKILL.md +54 -0
- package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -0
- package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -0
- package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -0
- package/.agents/skills/file-and-report-validator/SKILL.md +90 -0
- package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +114 -0
- package/.agents/skills/github-actions-templates/SKILL.md +334 -0
- package/.agents/skills/graphify-impact-analyzer/SKILL.md +78 -0
- package/.agents/skills/katalon-cli-runner/SKILL.md +76 -0
- package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -0
- package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -0
- package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -0
- package/.agents/skills/lam-script-generator/SKILL.md +83 -0
- package/.agents/skills/playwright-live-interaction/SKILL.md +86 -0
- package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -0
- package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -0
- package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -0
- package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -0
- package/.agents/skills/security-dast-sentinel/SKILL.md +176 -0
- package/.agents/skills/self-healing-locator/SKILL.md +73 -0
- package/.agents/skills/synthetic-test-data-generator/SKILL.md +135 -0
- package/.agents/skills/token-and-context-optimizer/SKILL.md +70 -0
- package/.agents/skills/visual-regression-sentinel/SKILL.md +62 -0
- package/.agents/skills/wcag-audit-patterns/SKILL.md +77 -0
- package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -0
- package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +65 -0
- package/.agents/templates/completion_report.md +57 -0
- package/.agents/workflows/graphify.md +10 -0
- package/.agents/workflows/test-impact.md +15 -0
- package/.agents/workflows/verify.md +34 -0
- package/AGENTS.md +115 -0
- package/README.md +394 -2
- package/bin/agent-qa.js +90 -0
- package/package.json +59 -4
- package/skills_manifest.json +262 -0
- package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +97 -0
- package/templates/PROJECT_STATE_TEMPLATE.md +20 -0
- package/tools/TOOLS_RUNBOOK.md +298 -0
- package/tools/agent_canary.py +501 -0
- package/tools/analyze_project.py +242 -0
- package/tools/api_drift_sentinel.py +208 -0
- package/tools/auto_heal.py +189 -0
- package/tools/browser_helpers.js +593 -0
- package/tools/bug_reporter.py +224 -0
- package/tools/cache_resolver.py +846 -0
- package/tools/check_env.py +288 -0
- package/tools/ci_healing_hook.py +128 -0
- package/tools/cli.py +402 -0
- package/tools/config_decoupler.py +253 -0
- package/tools/db_sandbox.py +341 -0
- package/tools/distill_log.py +152 -0
- package/tools/e2e_flow_prober.ps1 +65 -0
- package/tools/flaky_detector.py +222 -0
- package/tools/fuzz_payloads.py +197 -0
- package/tools/generate_allure_report.ps1 +30 -0
- package/tools/generate_api_matrix.py +193 -0
- package/tools/generate_tc_from_story.py +182 -0
- package/tools/generate_test_reports.ps1 +135 -0
- package/tools/git_pre_commit_guard.py +203 -0
- package/tools/heal_pr_automator.py +195 -0
- package/tools/heuristic_locator_matcher.py +202 -0
- package/tools/infer_linter.py +238 -0
- package/tools/lint_ai_docs.py +254 -0
- package/tools/lookup_tc.py +165 -0
- package/tools/lookup_xpath.py +167 -0
- package/tools/matrix_sharder.py +146 -0
- package/tools/mcp_excel_server.ps1 +251 -0
- package/tools/mcp_server.py +490 -0
- package/tools/micro_mutator.py +309 -0
- package/tools/network_mock_shield.py +170 -0
- package/tools/omni_emitter.py +500 -0
- package/tools/omni_parser.py +435 -0
- package/tools/omni_transpiler.py +168 -0
- package/tools/pinpoint_failure.py +88 -0
- package/tools/project_state.py +169 -0
- package/tools/repo_map.json +12 -0
- package/tools/repo_map.py +277 -0
- package/tools/repo_map.txt +7 -0
- package/tools/safety_firewall.py +245 -0
- package/tools/setup_project.py +265 -0
- package/tools/smart_visual_masker.py +134 -0
- package/tools/test_impact.py +321 -0
- package/tools/tms_sync_bridge.py +342 -0
- package/tools/trace_data_flow.py +240 -0
- package/tools/traffic_session_converter.py +256 -0
- package/tools/universal_ir.py +480 -0
- package/tools/validate_groovy_scripts.py +173 -0
- package/tools/verify_all.py +496 -0
- package/tools/verify_all.sh +4 -0
- package/tools/visual_diff_canvas.py +142 -0
- package/tools/visual_som_helper.py +418 -0
- package/tools/wcag_audit.py +214 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-dast-sentinel
|
|
3
|
+
description: Dynamic Application Security Testing (DAST) and OWASP Top 10 automated verification for web apps and APIs. Audits security response headers (CSP, HSTS, X-Frame-Options), detects sensitive data leaks (PII, tokens, internal stacktraces), asserts BOLA/IDOR authorization boundaries via role token swapping, and validates CORS configurations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Security DAST Sentinel (Dynamic Application Security & OWASP Top 10)
|
|
7
|
+
|
|
8
|
+
> **Purpose:** Automated Dynamic Application Security Testing (DAST) and defensive runtime verification across enterprise web applications and REST/GraphQL APIs. Bridges functional automated testing with OWASP Top 10 defensive compliance gates.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Core Defensive Scope & OWASP Top 10 Coverage
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
flowchart TD
|
|
16
|
+
A["<b>Security DAST Sentinel</b><br/>Runtime Defensive Verification"] --> B["<b>1. HTTP Security Headers</b><br/>CSP, HSTS, X-Frame-Options, MIME Sniff"]
|
|
17
|
+
A --> C["<b>2. Sensitive Data Exposure</b><br/>PII, Secrets, Tokens, Stacktrace Leakage"]
|
|
18
|
+
A --> D["<b>3. Broken Object Auth (BOLA/IDOR)</b><br/>Horizontal/Vertical Role Token Swapping"]
|
|
19
|
+
A --> E["<b>4. CORS & Origin Misconfig</b><br/>Origin Reflection, Credentials Wildcard"]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
| OWASP Category | Threat Vector | Automated Defensive Check | Assertion Target |
|
|
23
|
+
| :--- | :--- | :--- | :--- |
|
|
24
|
+
| **A01: Broken Access Control** | BOLA / IDOR | Swapping User A's Bearer token into User B's resource URI | HTTP `403 Forbidden` or `404 Not Found` (Never `200 OK`) |
|
|
25
|
+
| **A01: Broken Access Control** | CORS Misconfiguration | Sending unauthorized `Origin` header with `Credentials: include` | Must NOT reflect origin with `Access-Control-Allow-Credentials: true` |
|
|
26
|
+
| **A02: Cryptographic Failures** | Insecure Transport & Missing HSTS | Inspecting headers on HTTPS endpoints | `Strict-Transport-Security: max-age=31536000; includeSubDomains` |
|
|
27
|
+
| **A05: Security Misconfiguration** | Missing Security Headers | Passive audit on all page navigations & API responses | CSP, X-Frame-Options, X-Content-Type-Options: nosniff |
|
|
28
|
+
| **A05: Security Misconfiguration** | Verbose Error Disclosure | Injecting invalid payload to trigger 4xx/5xx | Response must NOT contain `SQLException`, `Traceback`, or internal paths |
|
|
29
|
+
| **A09: Security Logging & Monitoring** | Sensitive Data Leakage | Regex scan on API responses and local storage | Zero plaintext passwords, credit cards, or private keys |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. HTTP Security Response Headers Audit
|
|
34
|
+
|
|
35
|
+
All production and staging responses must enforce strict defensive headers to prevent Clickjacking, Cross-Site Scripting (XSS), and MIME-sniffing attacks.
|
|
36
|
+
|
|
37
|
+
### Mandatory Security Header Policy
|
|
38
|
+
1. `Content-Security-Policy`: Must define `default-src 'self'` or restrictive directive; must avoid `'unsafe-eval'` or open wildcards `*` in script sources.
|
|
39
|
+
2. `Strict-Transport-Security`: `max-age=31536000; includeSubDomains` on HTTPS.
|
|
40
|
+
3. `X-Frame-Options`: `DENY` or `SAMEORIGIN` (prevents UI clickjacking in external iframes).
|
|
41
|
+
4. `X-Content-Type-Options`: `nosniff` (prevents browser MIME-type confusion).
|
|
42
|
+
5. `Referrer-Policy`: `strict-origin-when-cross-origin` or `no-referrer`.
|
|
43
|
+
6. `Permissions-Policy`: Restricts camera, microphone, and geolocation APIs.
|
|
44
|
+
|
|
45
|
+
### Playwright Automated Headers Fixture (TypeScript)
|
|
46
|
+
```typescript
|
|
47
|
+
import { test, expect } from '@playwright/test';
|
|
48
|
+
|
|
49
|
+
test.describe('DAST Security Headers Audit', () => {
|
|
50
|
+
test('verify mandatory security headers on target application', async ({ page }) => {
|
|
51
|
+
const response = await page.goto('/dashboard');
|
|
52
|
+
expect(response).not.toBeNull();
|
|
53
|
+
const headers = response!.headers();
|
|
54
|
+
|
|
55
|
+
// 1. Clickjacking Protection
|
|
56
|
+
const xFrame = headers['x-frame-options']?.toUpperCase();
|
|
57
|
+
expect(['DENY', 'SAMEORIGIN'], 'X-Frame-Options must be DENY or SAMEORIGIN').toContain(xFrame);
|
|
58
|
+
|
|
59
|
+
// 2. MIME Sniffing Protection
|
|
60
|
+
expect(headers['x-content-type-options'], 'Must prevent MIME sniffing').toBe('nosniff');
|
|
61
|
+
|
|
62
|
+
// 3. Strict Transport Security
|
|
63
|
+
if (page.url().startsWith('https://')) {
|
|
64
|
+
expect(headers['strict-transport-security'], 'HSTS must be enabled on HTTPS').toContain('max-age=');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 4. Content Security Policy
|
|
68
|
+
const csp = headers['content-security-policy'];
|
|
69
|
+
expect(csp, 'Content-Security-Policy must be declared').toBeTruthy();
|
|
70
|
+
expect(csp).not.toContain("default-src *");
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 3. Sensitive Data Exposure (PII, Secrets & Error Leakage)
|
|
78
|
+
|
|
79
|
+
API responses and client-side storage must never leak internal stack traces, system paths, unmasked PII, or authorization credentials.
|
|
80
|
+
|
|
81
|
+
### Automated Response Interceptor Linter (Python / Playwright)
|
|
82
|
+
```python
|
|
83
|
+
import re
|
|
84
|
+
from typing import Dict, List
|
|
85
|
+
|
|
86
|
+
# Patterns matching accidental secret or stacktrace leakage
|
|
87
|
+
SENSITIVE_LEAK_PATTERNS = [
|
|
88
|
+
(re.compile(r'-----BEGIN (?:RSA )?PRIVATE KEY-----'), "Exposed Private Key"),
|
|
89
|
+
(re.compile(r'(?i)\b(?:password|passwd|pwd)\b\s*[:=]\s*["\'][^"\']{4,}["\']'), "Exposed Plaintext Password"),
|
|
90
|
+
(re.compile(r'\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})\b'), "Raw Credit Card Number (Visa/MC)"),
|
|
91
|
+
(re.compile(r'(?i)(?:SQLException|HibernateException|org\.postgresql\.util|java\.lang\.NullPointerException)'), "Database Stacktrace Leak"),
|
|
92
|
+
(re.compile(r'(?i)(?:Traceback \(most recent call last\)|File "[a-zA-Z0-9_\-\\/]+\.py", line \d+)'), "Python Stacktrace Leak"),
|
|
93
|
+
(re.compile(r'\b[a-zA-Z]:\\[a-zA-Z0-9_.\-\\]+\b'), "Internal Windows File Path Leak"),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
def scan_response_for_leaks(body_text: str) -> List[str]:
|
|
97
|
+
"""Inspects API response text for prohibited sensitive data leaks."""
|
|
98
|
+
violations = []
|
|
99
|
+
for pattern, description in SENSITIVE_LEAK_PATTERNS:
|
|
100
|
+
if pattern.search(body_text):
|
|
101
|
+
violations.append(description)
|
|
102
|
+
return violations
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 4. Broken Object-Level Authorization (BOLA / IDOR) Testing
|
|
108
|
+
|
|
109
|
+
BOLA occurs when an API endpoint uses user-supplied IDs to retrieve object instances without validating user ownership.
|
|
110
|
+
|
|
111
|
+
### Automated Dual-Role Permutation Protocol
|
|
112
|
+
1. **User A (Victim):** Log in and create Entity `X` (ID: `10042`).
|
|
113
|
+
2. **User B (Attacker):** Log in as an unrelated user or tenant, acquire Token `B`.
|
|
114
|
+
3. **Execute Cross-Tenant Query:** Dispatch `GET /api/v1/entities/10042` with `Authorization: Bearer <Token_B>`.
|
|
115
|
+
4. **Assert Access Barrier:**
|
|
116
|
+
- `HTTP 403 Forbidden` or `HTTP 404 Not Found` => **PASS** (Zero BOLA).
|
|
117
|
+
- `HTTP 200 OK` with Entity `X` payload => **CRITICAL DEFECT: BOLA / IDOR VULNERABILITY**.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
test('BOLA Defense: Tenant B cannot access Tenant A entity', async ({ request }) => {
|
|
121
|
+
// Tenant A creates resource
|
|
122
|
+
const createRes = await request.post('/api/v1/invoices', {
|
|
123
|
+
headers: { 'Authorization': `Bearer ${tokenTenantA}` },
|
|
124
|
+
data: { amount: 5000, description: 'Confidential Invoice A' }
|
|
125
|
+
});
|
|
126
|
+
const invoiceId = (await createRes.json()).id;
|
|
127
|
+
|
|
128
|
+
// Tenant B attempts to read Tenant A's invoice
|
|
129
|
+
const readAttempt = await request.get(`/api/v1/invoices/${invoiceId}`, {
|
|
130
|
+
headers: { 'Authorization': `Bearer ${tokenTenantB}` }
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Assertion: System must block cross-tenant read
|
|
134
|
+
expect([403, 404], 'Tenant B must not access Tenant A invoice').toContain(readAttempt.status());
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 5. CORS Misconfiguration Audit
|
|
141
|
+
|
|
142
|
+
CORS policies must never reflect arbitrary untrusted origins when credentials (cookies/tokens) are supported.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
test('CORS Defense: Server must not reflect arbitrary untrusted Origin with credentials', async ({ request }) => {
|
|
146
|
+
const untrustedOrigin = 'https://untrusted-attacker.com';
|
|
147
|
+
const response = await request.get('/api/v1/user/profile', {
|
|
148
|
+
headers: {
|
|
149
|
+
'Origin': untrustedOrigin,
|
|
150
|
+
'Authorization': `Bearer ${validUserToken}`
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const allowOrigin = response.headers()['access-control-allow-origin'];
|
|
155
|
+
const allowCredentials = response.headers()['access-control-allow-credentials'];
|
|
156
|
+
|
|
157
|
+
// Critical CORS Flaw: Reflecting untrusted origin while allowing credentials
|
|
158
|
+
if (allowOrigin === untrustedOrigin && allowCredentials === 'true') {
|
|
159
|
+
throw new Error('CRITICAL CORS VULNERABILITY: Arbitrary origin reflection with credentials enabled');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Critical CORS Flaw: Wildcard with credentials
|
|
163
|
+
if (allowOrigin === '*' && allowCredentials === 'true') {
|
|
164
|
+
throw new Error('CRITICAL CORS VULNERABILITY: Wildcard origin with credentials enabled');
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 6. Security DoD Verification Checklist
|
|
172
|
+
- [ ] Mandatory security headers verified on root and core dashboard routes.
|
|
173
|
+
- [ ] No `500 Server Error` response contains raw SQL exceptions or language stacktraces.
|
|
174
|
+
- [ ] All ID-based mutation and query endpoints verified against BOLA/IDOR permutations.
|
|
175
|
+
- [ ] CORS policies enforce whitelist or block `Credentials: true` with arbitrary origins.
|
|
176
|
+
- [ ] All security testing conducted non-destructively in defensive QA test suites.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: self-healing-locator
|
|
3
|
+
description: >-
|
|
4
|
+
Token-efficient self-healing locator skill using Accessibility Tree (AOM) and semantic DOM diffing with Role > Label > TestId hierarchy, avoiding raw HTML bloat.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Self-Healing Locator Skill — Token-Efficient AOM Diffing
|
|
8
|
+
|
|
9
|
+
This skill provides an automated, token-conservative mechanism to diagnose, diff, and repair broken web element locators across web applications without overwhelming the LLM context window with raw HTML dumps.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. The Token Conservation Principle
|
|
14
|
+
|
|
15
|
+
- **Raw HTML DOM Problem:** Dumping a complete HTML webpage into the prompt can consume 50,000 to 150,000 tokens, degrading AI reasoning and triggering context rot.
|
|
16
|
+
- **AOM Subtree Solution:** Extract exclusively the **Accessibility Object Model (AOM)** tree or a 2-hop semantic DOM subtree surrounding the target element, consuming under **500 tokens**.
|
|
17
|
+
|
|
18
|
+
```mermaid
|
|
19
|
+
flowchart LR
|
|
20
|
+
Broken["Broken Locator Encountered"] --> Probe["Extract Compact AOM Tree (500 tokens)"]
|
|
21
|
+
Probe --> Rank["Apply Hierarchy: Role > Label > TestId"]
|
|
22
|
+
Rank --> Test["Verify Uniqueness on Live DOM"]
|
|
23
|
+
Test --> Patch["Patch Page Class Method"]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Master Locator Ranking Hierarchy
|
|
29
|
+
|
|
30
|
+
When searching for a replacement locator, evaluate candidates in this strict priority order:
|
|
31
|
+
|
|
32
|
+
1. **Tier 1 — ARIA Role & Accessible Name:**
|
|
33
|
+
- Playwright: `page.getByRole('button', { name: 'Thêm mới' })`
|
|
34
|
+
- CSS: `[role="button"][aria-label="Thêm mới"]`
|
|
35
|
+
2. **Tier 2 — Form Control & Business Semantics:**
|
|
36
|
+
- `input[formcontrolname="code"]`
|
|
37
|
+
- `p-dropdown[formcontrolname="categoryId"]`
|
|
38
|
+
3. **Tier 3 — Dedicated Test Identifiers:**
|
|
39
|
+
- `[data-testid="btn-create"]`
|
|
40
|
+
- `[data-test="submit"]`
|
|
41
|
+
4. **Tier 4 — Stable Visual Text:**
|
|
42
|
+
- `button:has-text("Xác nháºn")`
|
|
43
|
+
5. **Tier 5 — Scoped Resilient Relative CSS:**
|
|
44
|
+
- `.card.popup-data input.p-inputtext`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 3. In-Browser AOM Probing Snippet
|
|
49
|
+
|
|
50
|
+
Execute this compact JavaScript probe via Playwright or Chrome DevTools to locate the target node without dumping HTML:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// Extract interactive elements tree scoped to active modal or container
|
|
54
|
+
() => {
|
|
55
|
+
const container = document.querySelector('.p-dialog, .modal-content, form') || document.body;
|
|
56
|
+
const elements = container.querySelectorAll('button, input, select, textarea, p-dropdown, [role="button"]');
|
|
57
|
+
return Array.from(elements).map(el => ({
|
|
58
|
+
tag: el.tagName.toLowerCase(),
|
|
59
|
+
role: el.getAttribute('role') || el.type,
|
|
60
|
+
name: el.getAttribute('name') || el.getAttribute('formcontrolname') || el.id,
|
|
61
|
+
label: el.innerText?.trim() || el.getAttribute('aria-label') || el.placeholder,
|
|
62
|
+
testId: el.getAttribute('data-testid')
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 4. Healing Execution Checklist
|
|
70
|
+
|
|
71
|
+
1. **Verify Uniqueness:** Ensure the candidate locator matches exactly 1 element on the live DOM.
|
|
72
|
+
2. **Encapsulate in Page Class:** Update the locator constant or private selector inside the relevant Page Class (e.g. `BasePage` or domain Page Class).
|
|
73
|
+
3. **Never Leak to Test Scripts:** Test scripts must remain 100% clean of raw selectors.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: synthetic-test-data-generator
|
|
3
|
+
description: Generate robust, idempotent, and boundary-value synthetic test data (strings, numbers, emails, addresses, enterprise contracts, GIS coordinates) for automated test suites.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Synthetic Test Data Generator & Edge-Case Fuzzing Skill
|
|
7
|
+
|
|
8
|
+
> **Target:** Eliminate database collisions, race conditions in parallel testing, and stale fixture dependencies by dynamically generating valid, boundary-value, and edge-case fuzzing datasets.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Core Principles
|
|
13
|
+
|
|
14
|
+
1. **Idempotence & Unique Prefixing:**
|
|
15
|
+
- Every generated string or identifier must contain an execution timestamp or UUID prefix (`AUTO_1719500000_...`) to allow parallel test executions without unique-key database collisions.
|
|
16
|
+
2. **Boundary Value Testing (BVT):**
|
|
17
|
+
- Automatically cover equivalence partitions:
|
|
18
|
+
- Null / Empty / Whitespace-only strings.
|
|
19
|
+
- Max length limits (e.g. 255 chars, 1,024 chars, 10,000 chars text blocks).
|
|
20
|
+
- Special characters, emojis, SQL injection probe strings (`' OR '1'='1' -- `), XSS polyglots (`<img src=x onerror=console.warn('qa_xss')>`).
|
|
21
|
+
- Negative numbers, extreme floats, zero, boundary integer limits (`2^31 - 1`, `2^63 - 1`, `Number.MAX_SAFE_INTEGER`).
|
|
22
|
+
3. **Domain-Specific Constraints:**
|
|
23
|
+
- Tax IDs, phone numbers, email RFC formats, and GIS coordinates (e.g., non-overlapping closed polygons).
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Standard Generation Recipes
|
|
28
|
+
|
|
29
|
+
### Recipe A: Dynamic Unique Entity Names
|
|
30
|
+
```typescript
|
|
31
|
+
export class TestDataFactory {
|
|
32
|
+
static uniqueName(prefix: string = 'AUTO'): string {
|
|
33
|
+
const timestamp = Date.now().toString(36).toUpperCase();
|
|
34
|
+
const randomSuffix = Math.random().toString(36).substring(2, 6).toUpperCase();
|
|
35
|
+
return `${prefix}_${timestamp}_${randomSuffix}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static validEmail(prefix: string = 'tester'): string {
|
|
39
|
+
return `${prefix}.${Date.now()}@example-testing.com`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Recipe B: Boundary Value String Suite
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"boundaryStrings": [
|
|
48
|
+
"",
|
|
49
|
+
" ",
|
|
50
|
+
"A",
|
|
51
|
+
"A".repeat(255),
|
|
52
|
+
"A".repeat(1024),
|
|
53
|
+
"Tiếng Việt có dấu: Cà phê sữa đá & Trắc nghiệm chất lượng",
|
|
54
|
+
"Special chars: !@#$%^&*()_+{}|:\"<>?~`-=[]\\;',./",
|
|
55
|
+
"Unicode emojis: 🚀🔥⚡🧪✨",
|
|
56
|
+
"XSS probe: <img src=x onerror=alert('qa')>",
|
|
57
|
+
"SQLi probe: ' OR '1'='1' -- "
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Recipe C: GeoJSON / GIS Valid Non-Overlapping Polygons
|
|
63
|
+
```typescript
|
|
64
|
+
export function generateValidPolygon(centerLat = 21.0285, centerLng = 105.8542, offset = 0.005) {
|
|
65
|
+
// Generates closed 5-point polygon bounding box
|
|
66
|
+
return [
|
|
67
|
+
[centerLng - offset, centerLat - offset],
|
|
68
|
+
[centerLng + offset, centerLat - offset],
|
|
69
|
+
[centerLng + offset, centerLat + offset],
|
|
70
|
+
[centerLng - offset, centerLat + offset],
|
|
71
|
+
[centerLng - offset, centerLat - offset] // Close ring
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3. Edge-Case Fuzzing & Input Sanitization Suite (`tools/fuzz_payloads.py`)
|
|
79
|
+
|
|
80
|
+
Transform functional tests into input sanitization and robustness validation by executing edge-case fuzzing vectors:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Query CLI catalog for specific field vectors
|
|
84
|
+
python tools/fuzz_payloads.py --field username --type string
|
|
85
|
+
python tools/fuzz_payloads.py --category sqli --json
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Recipe D: Harmless SQLi Polyglot Sanity
|
|
89
|
+
```typescript
|
|
90
|
+
export const SQLI_FUZZ_PROBES = [
|
|
91
|
+
"' OR '1'='1' -- ",
|
|
92
|
+
"SLEEP(0)/*'/*\"/*--",
|
|
93
|
+
"1' UNION SELECT NULL, NULL, NULL -- ",
|
|
94
|
+
"admin' -- ",
|
|
95
|
+
"'; WAITFOR DELAY '0:0:0'--"
|
|
96
|
+
];
|
|
97
|
+
// Assertion: Application must return HTTP 400 or sanitize safely; MUST NEVER throw 500 SQLException.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Recipe E: Unicode BiDi & RTL Trojan Source Vectors
|
|
101
|
+
```typescript
|
|
102
|
+
export const BIDI_FUZZ_PROBES = [
|
|
103
|
+
"\u202E\u0041\u0042\u0043_AUTO_TX", // Right-to-Left Override (RLO)
|
|
104
|
+
"AUTO\u200B\u200C\u200D_DATA", // Zero-Width Space & Joiner
|
|
105
|
+
"\uFEFFAUTO_USER", // In-string Byte Order Mark (BOM)
|
|
106
|
+
"USER_مرحبا_بالعالم_2026" // Mixed Latin/Arabic BiDi text
|
|
107
|
+
];
|
|
108
|
+
// Assertion: Database persistence and frontend display must not corrupt visual hierarchy or inject Trojan Source spoofing.
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Recipe F: Multi-Byte Emoji Surrogate Pairs & ZWJ Sequences
|
|
112
|
+
```typescript
|
|
113
|
+
export const EMOJI_FUZZ_PROBES = [
|
|
114
|
+
"👨👩👧👦_QA_RECORD", // Complex Zero-Width Joiner family sequence
|
|
115
|
+
"🏳️🌈_FLAG_TAG", // Multi-code point flag sequence
|
|
116
|
+
"\uD83D\uDE00\uD83D", // Unpaired surrogate boundary test
|
|
117
|
+
"🔥🚀⚡🧪✨" // 4-byte high-plane UTF-8 characters
|
|
118
|
+
];
|
|
119
|
+
// Assertion: Backend UTF-8 MB4 column encoding must persist without truncation or 1366 Incorrect string value error.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Recipe G: Extreme Length Buffer Stress ($10^4$ Characters)
|
|
123
|
+
```typescript
|
|
124
|
+
export const BUFFER_STRESS_PAYLOADS = [
|
|
125
|
+
"A".repeat(10000), // 10,000 chars text block
|
|
126
|
+
"X".repeat(1024), // Standard 1KB boundary
|
|
127
|
+
'{"test": [' + Array(500).fill('1').join(',') + ']}' // Repetitive JSON nesting
|
|
128
|
+
];
|
|
129
|
+
// Assertion: API must reject with 400/413 Payload Too Large; frontend form controls must enforce max-length clipping.
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 4. Teardown & Lifecycle Integration
|
|
135
|
+
- Every test generating persistent records with `synthetic-test-data-generator` **MUST** register the generated ID into a teardown queue to clean up after test execution completes.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: token-and-context-optimizer
|
|
3
|
+
description: Context engineering and token optimization skill for Antigravity, enforcing sparse context retrieval, log distillation, prevention of context degradation (Lost-in-the-Middle, attention sinks), and off-context memory scratchpad protocol.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Token & Context Optimizer — Antigravity Engineering Standard
|
|
7
|
+
|
|
8
|
+
> **Purpose:** Master context engineering and token efficiency. Directs AI Agents to prevent context rot, mitigate Lost-in-the-Middle attention drops, offload large state to filesystem scratchpads, and maintain clean KV-cache alignment across long test automation sessions.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. The Core Context Architecture
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
flowchart TD
|
|
16
|
+
P1["<b>1. Sparse Context Retrieval</b><br/>• Forbid cat on large files<br/>• Grep / Line-range only"] --> P2["<b>2. Terminal Log Distillation</b><br/>• Strip PASSED steps via tools/distill_log.py<br/>• Forward only FAILED stack trace"]
|
|
17
|
+
P2 --> P3["<b>3. File-Backed Memory Layer</b><br/>• Persist state to PROJECT_STATE.md<br/>• Zero conversational bloat"]
|
|
18
|
+
P3 --> P4["<b>4. Context Degradation Prevention</b><br/>• Attention U-Curve placement<br/>• Circuit break on hallucination poisoning"]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. Protocol 1: Sparse Context Retrieval
|
|
24
|
+
|
|
25
|
+
- **Rule:** Never read entire source files exceeding 150 lines into active context.
|
|
26
|
+
- **Enforcement:**
|
|
27
|
+
- Prohibit commands like `cat`, `type`, or unbounded `read_file` on large Page Classes (e.g. `DataMiningPage.groovy`).
|
|
28
|
+
- Use regex search (`grep -n`, `ripgrep`) or compressed maps (`tools/repo_map.txt`) to pinpoint signatures.
|
|
29
|
+
- Read strictly the targeted 20–50 lines using `StartLine` and `EndLine` parameters.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 3. Protocol 2: Terminal Log Distiller (`tools/distill_log.py`)
|
|
34
|
+
|
|
35
|
+
- **Rule:** Never dump unparsed execution logs (KRE CLI, Playwright stdout, Gradle) into the active conversation.
|
|
36
|
+
- **Enforcement:**
|
|
37
|
+
- Automatically filter out passing step messages, INFO logs, and JVM loading notices.
|
|
38
|
+
- Forward strictly the distilled failure block:
|
|
39
|
+
```text
|
|
40
|
+
[FAILED] TC-xxx at Line <LineNumber>
|
|
41
|
+
Exception: <ExceptionName> (<Message>)
|
|
42
|
+
[Full raw log saved to file://<path>; verbose lines omitted]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 4. Protocol 3: Task Scratchpad & File-Backed Context
|
|
48
|
+
|
|
49
|
+
- **Rule:** Do not accumulate large session state, test case inventories, or defect logs inside conversational prompt turns.
|
|
50
|
+
- **Enforcement:**
|
|
51
|
+
- Use the filesystem as the primary overflow memory layer.
|
|
52
|
+
- Persist ephemeral task tracking and defect registers to disk in structured markdown files (e.g. `PROJECT_STATE.md`, `KNOWN_ISSUES.md`, or `<appDataDir>/brain/<id>/scratch/`).
|
|
53
|
+
- Prefer dynamic context discovery (pulling context on demand via search tools) over static bulk inclusion.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 5. Protocol 4: Mitigating Context Degradation & Lost-in-the-Middle
|
|
58
|
+
|
|
59
|
+
- **Attention U-Curve Principle:** Models recall information at the beginning (BOS / System Prompt) and end (latest turn) far better than information buried in the middle of long sessions (> 4,000 tokens).
|
|
60
|
+
- **Enforcement:**
|
|
61
|
+
- Place critical instructions and current objective anchors at the beginning and end of prompts.
|
|
62
|
+
- Segment multi-module tasks into discrete sub-agent scopes to prevent cross-task confusion.
|
|
63
|
+
- **Context Poisoning Circuit Breaker:** If a tool output or test run produces an invalid assumption or hallucination, truncate reasoning immediately and re-anchor against verified disk state rather than compounding false premises.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 6. Protocol 5: KV-Cache Friendly Ordering
|
|
68
|
+
- Maintain immutable static instruction prefixes at the top.
|
|
69
|
+
- Append new dynamic observations strictly at the bottom.
|
|
70
|
+
- Use uniform pre-flight header formats to achieve > 85% inference KV-cache hit rate.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: visual-regression-sentinel
|
|
3
|
+
description: Pixel-level and perceptual visual regression testing with dynamic masking, layout shift detection, and threshold-based visual assertions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Visual Regression Sentinel Skill
|
|
7
|
+
|
|
8
|
+
> **Target:** Catch unintended UI rendering defects, CSS breakages, alignment shifts, and missing visual assets across viewports without manual visual inspection.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Core Principles
|
|
13
|
+
|
|
14
|
+
1. **Anti-Flakiness Masking:**
|
|
15
|
+
- Always mask dynamic elements (timers, timestamps, random avatars, ads, blinking carets) before capturing baselines.
|
|
16
|
+
2. **Perceptual Diffing over Strict Pixel Match:**
|
|
17
|
+
- Use SSIM (Structural Similarity Index) or perceptual threshold (`threshold: 0.2`) to tolerate minor antialiasing discrepancies between GPU rendering pipelines.
|
|
18
|
+
3. **Deterministic Viewports:**
|
|
19
|
+
- Standardize viewport dimensions (`1920x1080` for Desktop, `390x844` for Mobile) and disable animations (`animations: 'disabled'`).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. Standard Playwright Visual Assertion Patterns
|
|
24
|
+
|
|
25
|
+
### Pattern A: Full-Page Screenshot with Dynamic Masking
|
|
26
|
+
```typescript
|
|
27
|
+
await expect(page).toHaveScreenshot('landing-page.png', {
|
|
28
|
+
fullPage: true,
|
|
29
|
+
animations: 'disabled',
|
|
30
|
+
mask: [
|
|
31
|
+
page.locator('.dynamic-timestamp'),
|
|
32
|
+
page.locator('.live-ticker-banner'),
|
|
33
|
+
page.locator('[data-testid="unique-id-badge"]')
|
|
34
|
+
],
|
|
35
|
+
maxDiffPixelRatio: 0.02 // Allow 2% tolerance
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Pattern B: Component-Level Snapshot
|
|
40
|
+
```typescript
|
|
41
|
+
// Isolate critical component to avoid cascade failures from header/footer changes
|
|
42
|
+
const dataTable = page.locator('.custom-data-table');
|
|
43
|
+
await expect(dataTable).toHaveScreenshot('table-component-default.png', {
|
|
44
|
+
threshold: 0.1
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Pattern C: Color Mode / Responsive Variations
|
|
49
|
+
```typescript
|
|
50
|
+
// Test Dark Mode
|
|
51
|
+
await page.emulateMedia({ colorScheme: 'dark' });
|
|
52
|
+
await expect(page).toHaveScreenshot('dashboard-dark.png');
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 3. Visual Failure Autopsy Protocol
|
|
58
|
+
When visual regression fails:
|
|
59
|
+
1. Review generated diff image: `*-diff.png`.
|
|
60
|
+
2. Determine if it is a **Real Regression** (CSS bug, broken layout) or **Intentional Redesign**.
|
|
61
|
+
3. If intentional redesign: update baseline snapshots via `npx playwright test --update-snapshots`.
|
|
62
|
+
4. If bug: file bug report with side-by-side artifact comparison.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wcag-audit-patterns
|
|
3
|
+
description: Conduct WCAG 2.2 accessibility audits (Level A/AA) with automated AST analysis, keyboard trap verification, ARIA role assertions, and tools/wcag_audit.py.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# WCAG 2.2 Accessibility Audit Patterns
|
|
7
|
+
|
|
8
|
+
Engineering standards for automated, continuous Web Content Accessibility Guidelines (WCAG 2.2 Level A and AA) auditing across enterprise web applications.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Core WCAG 2.2 Success Criteria Matrix
|
|
13
|
+
|
|
14
|
+
| Criterion | Rule Code | Requirement & Automated Assertion |
|
|
15
|
+
| :--- | :--- | :--- |
|
|
16
|
+
| **Non-text Content** | WCAG 1.1.1 | All `<img>` tags must possess non-empty `alt` attributes or `aria-hidden="true"` if decorative. |
|
|
17
|
+
| **Info and Relationships**| WCAG 1.3.1 | Form controls `<input>`, `<select>` must link to `<label>` via `id/for` or `aria-label`. |
|
|
18
|
+
| **Heading Structure** | WCAG 1.3.1 | Headings must not skip levels (e.g. `<h1>` followed immediately by `<h3>`). |
|
|
19
|
+
| **Contrast (Minimum)** | WCAG 1.4.3 | Normal text contrast ratio $\ge 4.5:1$; Large text ($\ge 18\text{pt}$ or bold $14\text{pt}$) $\ge 3:1$. |
|
|
20
|
+
| **Keyboard Navigable** | WCAG 2.1.1 | All interactive elements must be focusable via `Tab` with visible focus indicators. |
|
|
21
|
+
| **No Keyboard Trap** | WCAG 2.1.2 | Focus must not become permanently trapped in modal dialogs; `Esc` key must exit. |
|
|
22
|
+
| **Target Size (Minimum)**| WCAG 2.5.8 | Interactive targets must meet $24 \times 24\text{px}$ minimum clickable area (WCAG 2.2 new). |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 2. Playwright Automated Accessibility Testing Patterns
|
|
27
|
+
|
|
28
|
+
### Pattern A: Integrating `@axe-core/playwright` for Comprehensive Audits
|
|
29
|
+
```typescript
|
|
30
|
+
import { test, expect } from '@playwright/test';
|
|
31
|
+
import AxeBuilder from '@axe-core/playwright';
|
|
32
|
+
|
|
33
|
+
test('verify WCAG 2.2 Level AA compliance on dashboard', async ({ page }) => {
|
|
34
|
+
await page.goto('/dashboard');
|
|
35
|
+
await page.waitForLoadState('networkidle');
|
|
36
|
+
|
|
37
|
+
const accessibilityScanResults = await new AxeBuilder({ page })
|
|
38
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'])
|
|
39
|
+
.exclude('.legacy-third-party-widget') // Explicitly scoped exclusion
|
|
40
|
+
.analyze();
|
|
41
|
+
|
|
42
|
+
expect(accessibilityScanResults.violations).toEqual([]);
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Pattern B: Modal Keyboard Focus Trap and Escape Verification
|
|
47
|
+
```typescript
|
|
48
|
+
test('modal dialog traps keyboard focus and closes on Escape', async ({ page }) => {
|
|
49
|
+
await page.goto('/settings');
|
|
50
|
+
await page.getByRole('button', { name: 'Edit Profile' }).click();
|
|
51
|
+
|
|
52
|
+
const modal = page.getByRole('dialog', { name: 'Edit Profile' });
|
|
53
|
+
await expect(modal).toBeVisible();
|
|
54
|
+
|
|
55
|
+
// Verify focus shifts into modal
|
|
56
|
+
await expect(modal.getByRole('textbox', { name: 'Username' })).toBeFocused();
|
|
57
|
+
|
|
58
|
+
// Press Escape and verify focus returns to trigger
|
|
59
|
+
await page.keyboard.press('Escape');
|
|
60
|
+
await expect(modal).toBeHidden();
|
|
61
|
+
await expect(page.getByRole('button', { name: 'Edit Profile' })).toBeFocused();
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 3. Automated CLI Auditing via Tooling
|
|
68
|
+
|
|
69
|
+
Agent can automatically audit accessibility for any HTML file or live page URL via `tools/wcag_audit.py`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Audit a local HTML snapshot
|
|
73
|
+
python tools/wcag_audit.py path/to/page.html -o docs/wcag_audit_report.md
|
|
74
|
+
|
|
75
|
+
# Audit a live application URL directly
|
|
76
|
+
python tools/wcag_audit.py https://staging.example.com --url -o docs/wcag_audit_report.md
|
|
77
|
+
```
|