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.
Files changed (122) hide show
  1. package/.agents/agents/failure-analyst.md +47 -0
  2. package/.agents/agents/live-explorer.md +41 -0
  3. package/.agents/agents/orchestrator.md +43 -0
  4. package/.agents/agents/pom-crafter.md +81 -0
  5. package/.agents/agents/quality-gatekeeper.md +47 -0
  6. package/.agents/agents/test-runner.md +43 -0
  7. package/.agents/rules/context-engineering.md +88 -0
  8. package/.agents/rules/git-push-protocol.md +101 -0
  9. package/.agents/rules/graphify.md +14 -0
  10. package/.agents/rules/lessons-learned.md +23 -0
  11. package/.agents/rules/mandatory-playwright-live.md +29 -0
  12. package/.agents/rules/skill-precedence.md +42 -0
  13. package/.agents/rules/systematic-debugging.md +99 -0
  14. package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +239 -0
  15. package/.agents/skills/antigravity-test-sentinel/SKILL.md +64 -0
  16. package/.agents/skills/api-network-mocking-interception/SKILL.md +142 -0
  17. package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +70 -0
  18. package/.agents/skills/architecture-decision-records/SKILL.md +441 -0
  19. package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +72 -0
  20. package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +214 -0
  21. package/.agents/skills/bats-testing-patterns/SKILL.md +100 -0
  22. package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -0
  23. package/.agents/skills/clean-pom-crafter/SKILL.md +75 -0
  24. package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -0
  25. package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -0
  26. package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +64 -0
  27. package/.agents/skills/code-refactoring-refactor-clean/resources/implementation-playbook.md +879 -0
  28. package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +123 -0
  29. package/.agents/skills/e2e-testing-patterns/SKILL.md +103 -0
  30. package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -0
  31. package/.agents/skills/failure-autopsy-and-healing/SKILL.md +54 -0
  32. package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -0
  33. package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -0
  34. package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -0
  35. package/.agents/skills/file-and-report-validator/SKILL.md +90 -0
  36. package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +114 -0
  37. package/.agents/skills/github-actions-templates/SKILL.md +334 -0
  38. package/.agents/skills/graphify-impact-analyzer/SKILL.md +78 -0
  39. package/.agents/skills/katalon-cli-runner/SKILL.md +76 -0
  40. package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -0
  41. package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -0
  42. package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -0
  43. package/.agents/skills/lam-script-generator/SKILL.md +83 -0
  44. package/.agents/skills/playwright-live-interaction/SKILL.md +86 -0
  45. package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -0
  46. package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -0
  47. package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -0
  48. package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -0
  49. package/.agents/skills/security-dast-sentinel/SKILL.md +176 -0
  50. package/.agents/skills/self-healing-locator/SKILL.md +73 -0
  51. package/.agents/skills/synthetic-test-data-generator/SKILL.md +135 -0
  52. package/.agents/skills/token-and-context-optimizer/SKILL.md +70 -0
  53. package/.agents/skills/visual-regression-sentinel/SKILL.md +62 -0
  54. package/.agents/skills/wcag-audit-patterns/SKILL.md +77 -0
  55. package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -0
  56. package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +65 -0
  57. package/.agents/templates/completion_report.md +57 -0
  58. package/.agents/workflows/graphify.md +10 -0
  59. package/.agents/workflows/test-impact.md +15 -0
  60. package/.agents/workflows/verify.md +34 -0
  61. package/AGENTS.md +115 -0
  62. package/README.md +394 -2
  63. package/bin/agent-qa.js +90 -0
  64. package/package.json +59 -4
  65. package/skills_manifest.json +262 -0
  66. package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +97 -0
  67. package/templates/PROJECT_STATE_TEMPLATE.md +20 -0
  68. package/tools/TOOLS_RUNBOOK.md +298 -0
  69. package/tools/agent_canary.py +501 -0
  70. package/tools/analyze_project.py +242 -0
  71. package/tools/api_drift_sentinel.py +208 -0
  72. package/tools/auto_heal.py +189 -0
  73. package/tools/browser_helpers.js +593 -0
  74. package/tools/bug_reporter.py +224 -0
  75. package/tools/cache_resolver.py +846 -0
  76. package/tools/check_env.py +288 -0
  77. package/tools/ci_healing_hook.py +128 -0
  78. package/tools/cli.py +402 -0
  79. package/tools/config_decoupler.py +253 -0
  80. package/tools/db_sandbox.py +341 -0
  81. package/tools/distill_log.py +152 -0
  82. package/tools/e2e_flow_prober.ps1 +65 -0
  83. package/tools/flaky_detector.py +222 -0
  84. package/tools/fuzz_payloads.py +197 -0
  85. package/tools/generate_allure_report.ps1 +30 -0
  86. package/tools/generate_api_matrix.py +193 -0
  87. package/tools/generate_tc_from_story.py +182 -0
  88. package/tools/generate_test_reports.ps1 +135 -0
  89. package/tools/git_pre_commit_guard.py +203 -0
  90. package/tools/heal_pr_automator.py +195 -0
  91. package/tools/heuristic_locator_matcher.py +202 -0
  92. package/tools/infer_linter.py +238 -0
  93. package/tools/lint_ai_docs.py +254 -0
  94. package/tools/lookup_tc.py +165 -0
  95. package/tools/lookup_xpath.py +167 -0
  96. package/tools/matrix_sharder.py +146 -0
  97. package/tools/mcp_excel_server.ps1 +251 -0
  98. package/tools/mcp_server.py +490 -0
  99. package/tools/micro_mutator.py +309 -0
  100. package/tools/network_mock_shield.py +170 -0
  101. package/tools/omni_emitter.py +500 -0
  102. package/tools/omni_parser.py +435 -0
  103. package/tools/omni_transpiler.py +168 -0
  104. package/tools/pinpoint_failure.py +88 -0
  105. package/tools/project_state.py +169 -0
  106. package/tools/repo_map.json +12 -0
  107. package/tools/repo_map.py +277 -0
  108. package/tools/repo_map.txt +7 -0
  109. package/tools/safety_firewall.py +245 -0
  110. package/tools/setup_project.py +265 -0
  111. package/tools/smart_visual_masker.py +134 -0
  112. package/tools/test_impact.py +321 -0
  113. package/tools/tms_sync_bridge.py +342 -0
  114. package/tools/trace_data_flow.py +240 -0
  115. package/tools/traffic_session_converter.py +256 -0
  116. package/tools/universal_ir.py +480 -0
  117. package/tools/validate_groovy_scripts.py +173 -0
  118. package/tools/verify_all.py +496 -0
  119. package/tools/verify_all.sh +4 -0
  120. package/tools/visual_diff_canvas.py +142 -0
  121. package/tools/visual_som_helper.py +418 -0
  122. package/tools/wcag_audit.py +214 -0
@@ -0,0 +1,388 @@
1
+ # Enterprise Playwright Code Recipes (20 Recipes)
2
+
3
+ All code recipes below execute directly via `browser_run_code_unsafe` with parameter `code: "async (page) => { ... }"`.
4
+
5
+ ---
6
+
7
+ ## Recipe 1: Authentication & Session Verification
8
+ ```javascript
9
+ async (page) => {
10
+ if (page.url().includes('/auth') || page.url().includes('/login')) {
11
+ const user = process.env.APP_USERNAME || 'your_username';
12
+ const pass = process.env.APP_PASSWORD || 'your_password';
13
+ await page.locator('input[formcontrolname="username"]').fill(user);
14
+ await page.locator('input[formcontrolname="password"]').fill(pass);
15
+ await page.locator('button[type="submit"]').click();
16
+ await page.waitForNavigation({ waitUntil: 'networkidle' });
17
+ }
18
+ return { currentUrl: page.url(), title: await page.title() };
19
+ }
20
+ ```
21
+
22
+ ## Recipe 2: Search, Filter & PrimeNG Table Verification (`p-table`)
23
+ ```javascript
24
+ async (page) => {
25
+ const searchInput = page.locator('input.p-inputtext[placeholder*="TΓ¬m kiαΊΏm"], input[placeholder*="tΓͺn"], input[placeholder*="mΓ£"]').first();
26
+ await searchInput.fill('HΓ  Nα»™i');
27
+ await searchInput.press('Enter');
28
+ await page.waitForTimeout(1000);
29
+
30
+ const rowCount = await page.locator('p-table table tbody tr').count();
31
+ const firstRowText = rowCount > 0 ? await page.locator('p-table table tbody tr').first().innerText() : '';
32
+ return { rowCount, firstRowText };
33
+ }
34
+ ```
35
+
36
+ ## Recipe 3: PrimeNG Dropdown & MultiSelect (`p-dropdown`, `p-multiselect`)
37
+ ```javascript
38
+ async (page) => {
39
+ const dropdown = page.locator('p-dropdown[formcontrolname="status"], p-dropdown[name="status"]').first();
40
+ await dropdown.click();
41
+ await page.waitForTimeout(400);
42
+
43
+ const option = page.locator('.p-dropdown-panel .p-dropdown-item').filter({ hasText: 'Đang hoαΊ‘t Δ‘α»™ng' }).first();
44
+ await option.click();
45
+ await page.waitForTimeout(300);
46
+
47
+ return { selectedLabel: await dropdown.locator('.p-dropdown-label').innerText() };
48
+ }
49
+ ```
50
+
51
+ ## Recipe 4: Modal Dialogs & Popup Forms (`p-dialog`, `.card.popup-data`)
52
+ ```javascript
53
+ async (page) => {
54
+ await page.evaluate(() => {
55
+ function setAngularInput(selector, val) {
56
+ const el = document.querySelector(selector);
57
+ if (el) {
58
+ el.value = val;
59
+ el.dispatchEvent(new Event('input', { bubbles: true }));
60
+ el.dispatchEvent(new Event('change', { bubbles: true }));
61
+ }
62
+ }
63
+ const testCode = 'CCN_' + Math.floor(Date.now() / 1000);
64
+ setAngularInput('input[formcontrolname="code"]', testCode);
65
+ setAngularInput('input[formcontrolname="name"]', 'Cα»₯m CΓ΄ng Nghiệp ' + testCode);
66
+ setAngularInput('textarea[formcontrolname="address"]', 'Địa chỉ kiểm thα»­ tα»± Δ‘α»™ng');
67
+ });
68
+
69
+ const saveBtn = page.locator('button:has-text("LΖ°u"), button:has-text("XΓ‘c nhαΊ­n"), button[title="XΓ‘c nhαΊ­n"]').first();
70
+ const isEnabled = !(await saveBtn.isDisabled());
71
+ if (isEnabled) {
72
+ await saveBtn.click();
73
+ await page.waitForTimeout(1500);
74
+ }
75
+ return { isSaveButtonEnabled: isEnabled };
76
+ }
77
+ ```
78
+
79
+ ## Recipe 5: Confirm Dialog & Deletion (`p-confirmdialog`)
80
+ ```javascript
81
+ async (page) => {
82
+ await page.locator('p-table tbody tr button.p-button-danger, p-table tbody tr button[icon*="trash"]').first().click();
83
+ await page.waitForTimeout(500);
84
+
85
+ const confirmBtn = page.locator('.p-confirm-dialog-accept, button:has-text("Đồng Γ½"), button:has-text("XΓ³a")').first();
86
+ await confirmBtn.click();
87
+ await page.waitForTimeout(1000);
88
+
89
+ const toastText = await page.locator('.p-toast-message-content').innerText().catch(() => 'No toast');
90
+ return { toastText };
91
+ }
92
+ ```
93
+
94
+ ## Recipe 6: File Upload & Excel Import (`input[type="file"]`)
95
+ ```javascript
96
+ async (page, customPath = 'Data Files/sample_import.xlsx') => {
97
+ const fs = require('fs');
98
+ const filePath = fs.existsSync(customPath) ? customPath : 'Data Files/sample_import.xlsx';
99
+ await page.locator('input[type="file"]').setInputFiles(filePath);
100
+ await page.waitForTimeout(1000);
101
+
102
+ await page.locator('button:has-text("TαΊ£i lΓͺn"), button:has-text("XΓ‘c nhαΊ­n")').first().click();
103
+ await page.waitForTimeout(2000);
104
+ return { status: "Uploaded", fileUsed: filePath };
105
+ }
106
+ ```
107
+
108
+ ## Recipe 7: OpenLayers GIS Canvas Interaction (`div.ol-viewport`)
109
+ ```javascript
110
+ async (page) => {
111
+ const canvas = page.locator('div.ol-viewport canvas').first();
112
+ const box = await canvas.boundingBox();
113
+ const cx = box.x + box.width / 2;
114
+ const cy = box.y + box.height / 2;
115
+
116
+ // Click polygon at non-overlapping offset (-180, -80)
117
+ await page.mouse.click(cx - 180, cy - 80);
118
+ await page.waitForTimeout(400);
119
+ await page.mouse.click(cx - 150, cy - 80);
120
+ await page.waitForTimeout(400);
121
+ await page.mouse.click(cx - 150, cy - 50);
122
+ await page.waitForTimeout(400);
123
+ await page.mouse.dblclick(cx - 180, cy - 80);
124
+ await page.waitForTimeout(1000);
125
+
126
+ const result = await page.evaluate(() => {
127
+ const error = document.querySelector('.text-danger, .invalid-feedback, editor-widget');
128
+ return {
129
+ hasError: !!error,
130
+ errorText: error ? error.innerText : ''
131
+ };
132
+ });
133
+ return result;
134
+ }
135
+ ```
136
+
137
+ ## Recipe 8: Advanced OpenLayers Map Inspection & VN2000 Coordinates
138
+ ```javascript
139
+ async (page) => {
140
+ return await page.evaluate(() => {
141
+ const viewport = document.querySelector('div.ol-viewport');
142
+ if (!viewport) return { error: "div.ol-viewport not found" };
143
+
144
+ const map = viewport['__ol_map__'] || (window.map instanceof Object ? window.map : null);
145
+ let mapInfo = {};
146
+ if (map && map.getView) {
147
+ const view = map.getView();
148
+ mapInfo = {
149
+ zoom: view.getZoom(),
150
+ center: view.getCenter(),
151
+ projection: view.getProjection() ? view.getProjection().getCode() : 'Unknown'
152
+ };
153
+ }
154
+ const toolbarButtons = Array.from(document.querySelectorAll('.ol-control button, .map-toolbar button, .gis-tools button'))
155
+ .map(b => ({ title: b.getAttribute('title') || b.innerText.trim(), className: b.className }));
156
+ return { mapInfo, toolbarButtons };
157
+ });
158
+ }
159
+ ```
160
+
161
+ ## Recipe 9: Two-Phase Search Workflow
162
+ ```javascript
163
+ async (page) => {
164
+ const searchToggleBtn = page.locator('button.p-button-icon-only[icon*="search"], button[title*="Tìm kiếm"], button:has-text("Tìm kiếm")').first();
165
+ const searchInput = page.locator('input.p-inputtext[placeholder*="TΓ¬m kiαΊΏm"], input[placeholder*="tΓͺn"], input[placeholder*="mΓ£"]').first();
166
+
167
+ if (!(await searchInput.isVisible())) {
168
+ await searchToggleBtn.click();
169
+ await page.waitForTimeout(300);
170
+ }
171
+
172
+ const keyword = 'CCN_TEST_2026';
173
+ await searchInput.fill(keyword);
174
+ await searchInput.press('Enter');
175
+ await page.waitForTimeout(1000);
176
+
177
+ const rowCount = await page.locator('p-table table tbody tr').count();
178
+ const matched = rowCount > 0 && (await page.locator('p-table table tbody tr').first().innerText()).includes(keyword);
179
+ return { rowCount, matched };
180
+ }
181
+ ```
182
+
183
+ ## Recipe 10: Intercepting PrimeNG Toasts (`p-toast`)
184
+ ```javascript
185
+ async (page) => {
186
+ const toastSelector = '.p-toast-message, .p-toast-message-content';
187
+ try {
188
+ const toast = await page.waitForSelector(toastSelector, { timeout: 4000 });
189
+ const text = await toast.innerText();
190
+ const isSuccess = (await toast.getAttribute('class') || '').includes('p-toast-message-success');
191
+ return { success: true, text, isSuccess };
192
+ } catch (e) {
193
+ return { success: false, message: 'Toast did not appear or expired too quickly' };
194
+ }
195
+ }
196
+ ```
197
+
198
+ ## Recipe 11: Record Deletion & Confirmation Dialog (`p-confirmdialog`)
199
+ ```javascript
200
+ async (page, targetKeyword) => {
201
+ const searchInput = page.locator('input.p-inputtext[placeholder*="TΓ¬m kiαΊΏm"], input[placeholder*="tΓͺn"], input[placeholder*="mΓ£"]').first();
202
+ await searchInput.fill(targetKeyword);
203
+ await searchInput.press('Enter');
204
+ await page.waitForTimeout(1000);
205
+
206
+ const deleteBtn = page.locator('p-table tbody tr:first-child button.p-button-danger, p-table tbody tr:first-child button[icon*="trash"]').first();
207
+ await deleteBtn.click();
208
+ await page.waitForTimeout(500);
209
+
210
+ const confirmBtn = page.locator('.p-confirm-dialog-accept, .p-dialog-footer button:has-text("XΓ³a"), .p-dialog-footer button:has-text("Đồng Γ½"), button.p-button-danger:has-text("XΓ³a")').first();
211
+ await confirmBtn.waitFor({ state: 'visible', timeout: 3000 });
212
+ await confirmBtn.click();
213
+ await page.waitForTimeout(1500);
214
+
215
+ await searchInput.fill(targetKeyword);
216
+ await searchInput.press('Enter');
217
+ await page.waitForTimeout(1000);
218
+ const remainingRows = await page.locator('p-table table tbody tr').count();
219
+ const firstRowText = remainingRows > 0 ? await page.locator('p-table table tbody tr').first().innerText() : '';
220
+ const isDeleted = remainingRows === 0 || !firstRowText.includes(targetKeyword) || firstRowText.includes('KhΓ΄ng cΓ³ dα»― liệu');
221
+
222
+ return { isDeleted, remainingRows, firstRowText };
223
+ }
224
+ ```
225
+
226
+ ## Recipe 12: PrimeNG Calendar Date Input (`p-calendar`)
227
+ ```javascript
228
+ async (page) => {
229
+ const dateValue = '25/10/2026';
230
+ await page.evaluate(({ selector, val }) => {
231
+ const calInput = document.querySelector(selector);
232
+ if (calInput) {
233
+ calInput.value = val;
234
+ calInput.dispatchEvent(new Event('input', { bubbles: true }));
235
+ calInput.dispatchEvent(new Event('change', { bubbles: true }));
236
+ calInput.dispatchEvent(new Event('blur', { bubbles: true }));
237
+ }
238
+ }, { selector: 'p-calendar input, input[formcontrolname*="date"], input[formcontrolname*="Date"]', val: dateValue });
239
+
240
+ await page.waitForTimeout(300);
241
+ return { status: 'Date filled', value: dateValue };
242
+ }
243
+ ```
244
+
245
+ ## Recipe 13: PrimeNG MultiSelect Dropdown (`p-multiselect`)
246
+ ```javascript
247
+ async (page, optionsToSelect = ['CΓ΄ng nghiệp chαΊΏ biαΊΏn', 'Điện lα»±c']) => {
248
+ const multiSelect = page.locator('p-multiselect').first();
249
+ await multiSelect.click();
250
+ await page.waitForSelector('.p-multiselect-panel', { state: 'visible', timeout: 3000 });
251
+ await page.waitForTimeout(300);
252
+
253
+ for (const optText of optionsToSelect) {
254
+ const item = page.locator('.p-multiselect-item').filter({ hasText: optText }).first();
255
+ if (await item.isVisible()) {
256
+ await item.click();
257
+ await page.waitForTimeout(200);
258
+ }
259
+ }
260
+
261
+ const closeBtn = page.locator('.p-multiselect-close').first();
262
+ if (await closeBtn.isVisible()) {
263
+ await closeBtn.click();
264
+ } else {
265
+ await page.keyboard.press('Escape');
266
+ }
267
+ await page.waitForTimeout(300);
268
+ return { selected: optionsToSelect };
269
+ }
270
+ ```
271
+
272
+ ## Recipe 14: Handling Stale Elements & Angular DOM Re-render Retries
273
+ ```javascript
274
+ async (page, actionFn) => {
275
+ const maxRetries = 3;
276
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
277
+ try {
278
+ return await actionFn(page);
279
+ } catch (err) {
280
+ if (err.message.includes('Element is not attached to the DOM') || err.message.includes('stale') || attempt === maxRetries) {
281
+ if (attempt === maxRetries) throw err;
282
+ await page.waitForTimeout(500 * attempt);
283
+ } else {
284
+ throw err;
285
+ }
286
+ }
287
+ }
288
+ }
289
+ ```
290
+
291
+
292
+ ## Recipe 15: Instant Angular Form Audit (Diagnose Disabled Save Button)
293
+ ```javascript
294
+ async (page) => {
295
+ return await page.evaluate(() => {
296
+ const invalidInputs = Array.from(document.querySelectorAll('form .ng-invalid, input.ng-invalid, p-dropdown.ng-invalid, textarea.ng-invalid'));
297
+ return invalidInputs.map(el => ({
298
+ tag: el.tagName.toLowerCase(),
299
+ control: el.getAttribute('formcontrolname') || el.getAttribute('name') || el.id || 'unnamed',
300
+ placeholder: el.getAttribute('placeholder') || '',
301
+ currentValue: el.value || el.innerText.trim()
302
+ }));
303
+ });
304
+ }
305
+ ```
306
+
307
+ ## Recipe 16: Smart Action Batching (Atomic Execution with Pause-on-Failure)
308
+ ```javascript
309
+ async (page) => {
310
+ return await page.evaluate(() => {
311
+ const steps = [
312
+ { name: 'fill_code', fn: () => { const el = document.querySelector("input[formcontrolname='code']"); el.value = 'CCN_TEST'; el.dispatchEvent(new Event('input', {bubbles: true})); } },
313
+ { name: 'fill_name', fn: () => { const el = document.querySelector("input[formcontrolname='name']"); el.value = 'Cα»₯m CN Test'; el.dispatchEvent(new Event('input', {bubbles: true})); } },
314
+ { name: 'submit', fn: () => { document.querySelector("button[type='submit']").click(); } }
315
+ ];
316
+
317
+ for (let i = 0; i < steps.length; i++) {
318
+ try {
319
+ steps[i].fn();
320
+ } catch (err) {
321
+ return { status: 'FAILED', failedStep: i + 1, name: steps[i].name, error: err.message, url: location.href };
322
+ }
323
+ }
324
+ return { status: 'SUCCESS', totalSteps: steps.length };
325
+ });
326
+ }
327
+ ```
328
+
329
+ ## Recipe 17: Runtime Helper Injection (`window.__qa`)
330
+ ```javascript
331
+ async (page) => {
332
+ // Injects the centralized browser helper tools/browser_helpers.js
333
+ const fs = require('fs');
334
+ const helperCode = fs.readFileSync('tools/browser_helpers.js', 'utf8');
335
+ await page.evaluate(helperCode);
336
+ return await page.evaluate(() => ({
337
+ version: window.__qa.__version,
338
+ auditResults: window.__qa.audit()
339
+ }));
340
+ }
341
+ ```
342
+
343
+ ## Recipe 18: Self-Healing Locator Fallback (`window.__qa.heal`)
344
+ ```javascript
345
+ async (page, brokenXPath, expectedText) => {
346
+ return await page.evaluate(({ xpath, text }) => {
347
+ if (window.__qa) {
348
+ return window.__qa.heal(xpath, text);
349
+ }
350
+ // Fallback search
351
+ const buttons = Array.from(document.querySelectorAll('button')).filter(b => b.innerText.includes(text));
352
+ return {
353
+ candidates: buttons.map(b => `//button[contains(normalize-space(.), '${b.innerText.trim()}')]`)
354
+ };
355
+ }, { xpath: brokenXPath, text: expectedText });
356
+ }
357
+ ```
358
+
359
+ ## Recipe 19: Overlay-Proof Safe Click (`window.__qa.clickSafe`)
360
+ ```javascript
361
+ async (page, selector) => {
362
+ return await page.evaluate((sel) => {
363
+ if (window.__qa) {
364
+ return window.__qa.clickSafe(sel);
365
+ }
366
+ const el = document.querySelector(sel);
367
+ if (!el) return false;
368
+ document.querySelectorAll('.p-component-overlay').forEach(o => o.style.pointerEvents = 'none');
369
+ el.click();
370
+ return true;
371
+ }, selector);
372
+ }
373
+ ```
374
+
375
+ ## Recipe 20: OpenLayers GIS Canvas Coordinate Inspector (`window.__qa.gisHUD`)
376
+ ```javascript
377
+ async (page) => {
378
+ return await page.evaluate(() => {
379
+ if (window.__qa) {
380
+ return window.__qa.gisHUD();
381
+ }
382
+ const vp = document.querySelector('.ol-viewport');
383
+ if (!vp) return { status: 'NO_MAP' };
384
+ const r = vp.getBoundingClientRect();
385
+ return { width: r.width, height: r.height, safeCenter: { x: r.width / 2, y: r.height / 2 } };
386
+ });
387
+ }
388
+ ```
@@ -0,0 +1,134 @@
1
+ # Enterprise Multi-Agent Swarm Orchestration Guide (Enterprise Automation)
2
+
3
+ Standard operating procedure, role taxonomy, and collaboration protocol for the **Enterprise Test Engineering Swarm** covering all 259 Test Cases.
4
+
5
+ ---
6
+
7
+ ## 1. Organizational Hierarchy & Role Taxonomy
8
+
9
+ ```mermaid
10
+ flowchart TD
11
+ Boss["πŸ‘‘ PROJECT LEAD (Test Manager / QA Director)<br/>(Strategic direction & final sign-off)"] --> Head["πŸ‘” LEAD QA ORCHESTRATOR<br/>(Overall coordination & quality governance)"]
12
+
13
+ subgraph SpecializedSwarm["SPECIALIZED AUTOMATION SWARM"]
14
+ Scout["πŸ” LIVE INTERACTION EXPLORER<br/>(DOM/AOM live probing via Playwright MCP)"]
15
+ Crafter["βš’οΈ AUTOMATION CODE CRAFTER<br/>(Page Classes & Clean POM Groovy scripts)"]
16
+ Runner["⚑ TEST EXECUTION RUNNER<br/>(Headless Katalon CLI execution)"]
17
+ Judge["πŸ›‘οΈ QUALITY GATEKEEPER & ANALYST<br/>(100% UTF-8 No BOM, anti-bypass & RCA)"]
18
+ Scribe["πŸ“– TECHNICAL DOCUMENTATION SPECIALIST<br/>(Business workflows & visual charting)"]
19
+ end
20
+
21
+ Head --> Scout & Crafter & Runner & Judge & Scribe
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 2. Enterprise Collaboration Protocol
27
+
28
+ 1. **User Communication (Project Lead):**
29
+ * Demeanor: Results-oriented, data-driven, concise, transparent.
30
+ * Language with user: Vietnamese (clear engineering terms).
31
+ 2. **Internal Agent-to-Agent Protocol:**
32
+ * **Lead QA Orchestrator:** Decomposes Acceptance Criteria, manages timeline, monitors SLAs.
33
+ * **Live Interaction Explorer:** Delivers validated JSON Data Contracts based on live DOM inspection.
34
+ * **Automation Code Crafter:** Implements Page Object Model code under test scrutiny from Runner and gatekeeping from Gatekeeper.
35
+ * **Quality Gatekeeper & Analyst:** Enforces quality standards independently; rejects fake passes; provides RCA evidence.
36
+ * **Technical Documentation Specialist:** Systematizes documentation, translates code into visual Mermaid workflows.
37
+
38
+ ---
39
+
40
+ ## 3. Specialized Role Responsibilities
41
+
42
+ ### πŸ‘‘ 1. Lead QA Orchestrator
43
+ * Receives objectives from Project Lead (e.g. *"Complete Industrial Clusters TC-66 to TC-80"*).
44
+ * Queries `tools/lookup_tc.py` to break down tasks into subagent batches.
45
+ * Invokes specialized subagents and synthesizes completion reports.
46
+
47
+ ### πŸ” 2. Live Interaction Explorer
48
+ * **Tools:** Playwright MCP (`browser_run_code_unsafe`, `browser_navigate`).
49
+ * **Tasks:**
50
+ - Loads `.agents/session.json` (Zero-Second Auth).
51
+ - Inspects live routes: URL, Title, interactive buttons, inputs, dropdown overlays.
52
+ - Verifies 100% selector hit rate on live browser.
53
+ - Returns compact JSON Data Contract to Code Crafter.
54
+
55
+ ### βš’οΈ 3. Automation Code Crafter
56
+ * **Tools:** File editing tools.
57
+ * **Tasks:**
58
+ - Consumes Data Contract from Explorer.
59
+ - Implements `public static` methods in `Keywords/pages/<PageClass>.groovy` inheriting `BasePage`.
60
+ - Generates corresponding test scripts (`Scripts/TC-xxx .../Script*.groovy`).
61
+ - Strict compliance with Flat Architecture and Clean POM (zero raw XPaths in test scripts).
62
+
63
+ ### ⚑ 4. Test Execution Runner
64
+ * **Tools:** Run command tools (`katalonc`, shell/PowerShell runners).
65
+ * **Tasks:**
66
+ - Executes targeted suites or batches in pure Headless Mode.
67
+ - Captures `Screenshots/FAILED_*.png` on failure; compiles Allure reports.
68
+ - Hands over results to Quality Gatekeeper.
69
+
70
+ ### πŸ›‘οΈ 5. Quality Gatekeeper & Failure Analyst
71
+ * **Tools:** Static checkers, test assertion validators.
72
+ * **Tasks:**
73
+ - Enforces 100% UTF-8 No BOM (`0xEF, 0xBB, 0xBF`).
74
+ - Rejects fake passes (verifies real toast notifications and table data).
75
+ - Conducts visual RCA via `triage_failures.sh` and `Screenshots/FAILED_*.png`.
76
+
77
+ ### πŸ“– 6. Technical Documentation Specialist
78
+ * **Tasks:**
79
+ - Translates `.groovy` scripts into plain business requirements.
80
+ - Generates Mermaid sequence and flowchart diagrams.
81
+ - Documents technical rationale (why specific coordinates or synthetic events are required).
82
+
83
+ ---
84
+
85
+ ## 4. Launching Swarm in Antigravity
86
+
87
+ - **Method 1 (UI Slash Command):** Type `/teamwork-preview` to visualize parallel subagents.
88
+ - **Method 2 (Autonomous Prompt):** Prompt: *"Act as Lead QA Orchestrator, dispatch Swarm to complete TC-123 through TC-127."*
89
+ * Orchestrator invokes `Live Explorer` for DOM probing.
90
+ * Next invokes `Code Crafter` to write Groovy code.
91
+ * Finally invokes `Quality Gatekeeper` for verification.
92
+
93
+ ---
94
+
95
+ ## 5. Multi-Agent Adversarial Debate
96
+
97
+ ```mermaid
98
+ sequenceDiagram
99
+ participant Crafter as βš’οΈ Automation Code Crafter
100
+ participant Explorer as πŸ” Live Interaction Explorer
101
+ participant Gatekeeper as πŸ›‘οΈ Quality Gatekeeper
102
+ participant Judge as πŸ‘‘ Lead QA Orchestrator
103
+
104
+ Crafter->>Explorer: "Created Supermarket method drawing Polygon at (-180, -80)."
105
+ Explorer-->>Crafter: "CHALLENGE: Live DOM shows Supermarket is POINT, not POLYGON! Will fail like TC-135."
106
+ Crafter->>Crafter: Refactors to clickPointOnCanvas().
107
+ Crafter->>Gatekeeper: "Submitted updated Point implementation."
108
+ Gatekeeper-->>Crafter: "CHALLENGE: Only delay(3) without verifying real success Toast. Fake pass detected!"
109
+ Crafter->>Crafter: Adds verifyMiningSuccess('thΓ nh cΓ΄ng').
110
+ Crafter->>Gatekeeper: "Added real Toast assertion + verified UTF-8 No BOM."
111
+ Gatekeeper->>Judge: "REPORT: Code 100% compliant."
112
+ Judge->>Judge: Consensus reached -> Commit code!
113
+ ```
114
+
115
+ ---
116
+
117
+ ## 6. Model Routing Strategy (Quota Optimization)
118
+
119
+ | Subagent Role | Recommended Model | Rationale & Tasks |
120
+ |---|:---:|---|
121
+ | **Quality Gatekeeper & Failure Analyst** | `flash` / `flash_lite` | Parses long KRE console logs, checks JUnit XML & BOM, ultra-fast (<0.5s), saves 70% quota. |
122
+ | **Test Execution Runner** | `flash` | Executes CLI runners, checks exit codes. |
123
+ | **Live Interaction Explorer** | `pro` / `inherit` | Complex DOM inspection, OpenLayers GIS navigation, AOM snapshots. |
124
+ | **Automation Code Crafter** | `pro` / `inherit` | Clean POM Groovy refactoring, Angular synthetic event handling. |
125
+ | **Lead QA Orchestrator** | `pro` / `inherit` | Acceptance Criteria decomposition and architectural decision-making. |
126
+
127
+ ---
128
+
129
+ ## 7. Auto Cleanup Blacklist
130
+
131
+ All Subagents **MUST** clean up temporary files before returning control to Orchestrator:
132
+ - Dumps: `*_debug.txt`, `debug_output.txt`, `dom_dump.txt`, `html_dump.html`, `network_requests.txt`, `console_log.txt`
133
+ - Snapshots: `page_snapshot.md`, `snapshot_*.md`, `.agents/screenshots/gis_canvas_live.png`
134
+ - Scratch files: `scratch_*.*`, `*.tmp`, `*.temp`