synapse-hub 2.4.3 ā 2.6.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 +13 -0
- package/.agents/agents/orchestrator.md +5 -2
- package/.agents/agents/pom-crafter.md +13 -0
- package/.agents/agents/quality-gatekeeper.md +21 -2
- package/.agents/agents/test-runner.md +11 -0
- package/.agents/rules/context-engineering.md +22 -102
- package/.agents/rules/mobile_appium_rules.md +19 -115
- package/.agents/rules/performance_testing_rules.md +18 -62
- package/.agents/rules/skill-precedence.md +24 -24
- package/.agents/rules/systematic-debugging.md +10 -27
- package/.agents/skills/lean-code-ladder/SKILL.md +12 -1
- package/.agents/skills/lean-impact-scoreboard/SKILL.md +48 -0
- package/.agents/skills/lean-impact-scoreboard/examples/sample_benchmark_gain.md +20 -0
- package/.agents/skills/lean-impact-scoreboard/examples/sample_scoreboard.md +15 -0
- package/.agents/skills/repo-quality-audit/SKILL.md +68 -0
- package/.agents/skills/repo-quality-audit/examples/sample_audit_walkthrough.md +15 -0
- package/.agents/skills/repo-quality-audit/examples/sample_repo_audit.md +33 -0
- package/.agents/skills/senior-code-review/SKILL.md +90 -0
- package/.agents/skills/senior-code-review/examples/sample_review_walkthrough.md +29 -0
- package/.agents/skills/technical-debt-harvester/SKILL.md +70 -0
- package/.agents/skills/technical-debt-harvester/examples/sample_debt_ledger.md +25 -0
- package/.agents/skills/technical-debt-harvester/examples/sample_ledger_output.md +20 -0
- package/.agents/skills/token-and-context-optimizer/references/context_engineering_guide.md +49 -0
- package/.cursor/rules/synapse-qa.mdc +4 -3
- package/.cursorrules +1 -0
- package/.windsurfrules +1 -0
- package/AGENTS.md +57 -180
- package/CLAUDE.md +5 -0
- package/NOTICE +40 -4
- package/README.en.md +33 -13
- package/README.md +36 -16
- package/bin/agent-qa.js +3 -2
- package/docs/ARCHITECTURE.md +39 -11
- package/docs/CLI_REFERENCE.md +15 -1
- package/docs/adopted-ecosystem-tools.md +9 -0
- package/docs/research/agent_skill_training_analysis.md +1357 -0
- package/package.json +1 -3
- package/skills_manifest.json +39 -3
- package/synapse.config.json +3 -2
- package/templates/ai_bridges/CLAUDE.md +5 -0
- package/templates/ai_bridges/copilot-instructions.md +2 -0
- package/templates/ai_bridges/cursor_synapse_qa.mdc +4 -3
- package/templates/ai_bridges/windsurfrules +1 -0
- package/templates/welcome.html.tmpl +34 -25
- package/tools/.infer_baseline.json +7 -1079
- package/tools/TOOLS_RUNBOOK.md +182 -13
- package/tools/__init__.py +1 -1
- package/tools/agent_canary.py +4 -4
- package/tools/analyze_project.py +2 -2
- package/tools/api_fuzzer.py +4 -4
- package/tools/auto_heal.py +14 -2
- package/tools/auto_heal_reflexion.py +172 -0
- package/tools/browser_helpers.js +57 -2
- package/tools/bump_version.py +30 -2
- package/tools/cache_resolver.py +6 -6
- package/tools/check_env.py +13 -7
- package/tools/cli.py +265 -197
- package/tools/count_tokens.py +7 -7
- package/tools/dashboard_generator.py +39 -23
- package/tools/db_sandbox.py +5 -5
- package/tools/debt_harvester.py +236 -0
- package/tools/distill_log.py +2 -2
- package/tools/dspy_qa_signatures.py +357 -0
- package/tools/flaky_detector.py +5 -5
- package/tools/generate_tc_from_story.py +2 -2
- package/tools/generate_test_reports.py +4 -4
- package/tools/git_pre_commit_guard.py +6 -6
- package/tools/infer_linter.py +12 -7
- package/tools/interview_story.py +117 -0
- package/tools/lint_ai_docs.py +3 -3
- package/tools/matrix_sharder.py +4 -4
- package/tools/mcp_excel_server.py +1 -1
- package/tools/mcp_server.py +3 -3
- package/tools/micro_mutator.py +6 -6
- package/tools/omni_transpiler.py +2 -2
- package/tools/output_formatter.py +37 -2
- package/tools/pinpoint_failure.py +4 -1
- package/tools/repo_map.py +2 -2
- package/tools/reversible_sandbox.py +157 -0
- package/tools/safety_firewall.py +30 -2
- package/tools/senior_code_review.py +341 -0
- package/tools/setup_project.py +9 -9
- package/tools/skill_collision_guard.py +231 -0
- package/tools/skill_vault.py +343 -0
- package/tools/skillspector.py +2 -2
- package/tools/synapse_qa_bench.py +190 -0
- package/tools/sync_agent_rules.py +14 -3
- package/tools/test_impact.py +4 -4
- package/tools/textgrad_mutation_optimizer.py +234 -0
- package/tools/tms_sync_bridge.py +2 -2
- package/tools/update_sentinel.py +17 -17
- package/tools/verify_all.py +47 -16
- package/tools/visual_som_helper.py +8 -8
- package/tools/watch_mode.py +7 -8
- package/tools/wcag_audit.py +5 -1
- package/tools/welcome_page.py +12 -12
- package/benchmarks/qa_eval/README.md +0 -71
- package/benchmarks/qa_eval/build_dataset.py +0 -677
- package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-06_api_contract_drift.json +0 -22
- package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-07_api_contract_drift.json +0 -22
- package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-08_api_contract_drift.json +0 -22
- package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-09_api_contract_drift.json +0 -22
- package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-10_api_contract_drift.json +0 -22
- package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-21_fake_pass_tautology.json +0 -21
- package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-22_fake_pass_tautology.json +0 -21
- package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-23_fake_pass_tautology.json +0 -21
- package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-24_fake_pass_tautology.json +0 -21
- package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-25_fake_pass_tautology.json +0 -21
- package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-01_locator_drift.json +0 -23
- package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-02_locator_drift.json +0 -23
- package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-03_locator_drift.json +0 -23
- package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-04_locator_drift.json +0 -23
- package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-05_locator_drift.json +0 -23
- package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-16_stale_and_mutation.json +0 -22
- package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-17_stale_and_mutation.json +0 -22
- package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-18_stale_and_mutation.json +0 -22
- package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-19_stale_and_mutation.json +0 -22
- package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-20_stale_and_mutation.json +0 -23
- package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-11_timing_and_race.json +0 -22
- package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-12_timing_and_race.json +0 -22
- package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-13_timing_and_race.json +0 -22
- package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-14_timing_and_race.json +0 -22
- package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-15_timing_and_race.json +0 -22
- package/benchmarks/qa_eval/eval_runner.py +0 -418
- package/examples/cypress-ecommerce-suite/README.md +0 -45
- package/examples/cypress-ecommerce-suite/cypress/e2e/checkout.cy.js +0 -17
- package/examples/cypress-ecommerce-suite/cypress/pages/BasePage.js +0 -29
- package/examples/cypress-ecommerce-suite/cypress/pages/CartPage.js +0 -51
- package/examples/cypress-ecommerce-suite/cypress.config.js +0 -13
- package/examples/cypress-ecommerce-suite/package.json +0 -13
- package/examples/katalon-suite/Keywords/pages/BasePage.groovy +0 -19
- package/examples/katalon-suite/Keywords/pages/DashboardPage.groovy +0 -29
- package/examples/katalon-suite/Keywords/pages/LoginPage.groovy +0 -45
- package/examples/katalon-suite/Profiles/default.glbl +0 -12
- package/examples/katalon-suite/README.md +0 -18
- package/examples/katalon-suite/Scripts/Auth/TC_LoginSuccess/Script1234567890.groovy +0 -12
- package/examples/katalon-suite/Scripts/Dashboard/TC_ViewSummary/Script1234567891.groovy +0 -15
- package/examples/katalon-suite/katalon_suite.prj +0 -21
- package/examples/playwright-crm-suite/README.md +0 -40
- package/examples/playwright-crm-suite/package.json +0 -14
- package/examples/playwright-crm-suite/pages/BasePage.ts +0 -37
- package/examples/playwright-crm-suite/pages/CustomerPage.ts +0 -57
- package/examples/playwright-crm-suite/pages/LoginPage.ts +0 -32
- package/examples/playwright-crm-suite/playwright.config.ts +0 -27
- package/examples/playwright-crm-suite/tests/auth.spec.ts +0 -22
- package/examples/playwright-crm-suite/tests/customers.spec.ts +0 -33
- package/examples/plugins/sample-custom-plugin/README.md +0 -14
- package/examples/plugins/sample-custom-plugin/plugin.json +0 -16
- package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/SKILL.md +0 -29
- package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/examples/audit_fixture.json +0 -8
- package/examples/plugins/sample-custom-plugin/tools/custom_security_headers.py +0 -125
- package/examples/practices/README.md +0 -22
- package/examples/practices/requirements/crm/requirements_contracts.md +0 -292
- package/examples/practices/requirements/crm/requirements_customers.md +0 -462
- package/examples/practices/requirements/crm/requirements_login.md +0 -202
- package/examples/practices/requirements/crm/requirements_projects.md +0 -396
- package/examples/practices/requirements/crm/requirements_tasks.md +0 -343
- package/examples/practices/requirements/ecommerce/requirements_category_brand.txt +0 -402
- package/examples/practices/requirements/jira/KAN-5/KAN-1/2026-04-03_04-28-27.png +0 -0
- package/examples/practices/requirements/jira/KAN-5/KAN-1/KAN-1_requirement.md +0 -52
- package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-19.png +0 -0
- package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-57.png +0 -0
- package/examples/practices/requirements/jira/KAN-5/KAN-4/KAN-4_requirement.md +0 -119
- package/examples/practices/requirements/jira/KAN-5/KAN-5_overview.md +0 -9
- package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-08.png +0 -0
- package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-23.png +0 -0
- package/examples/practices/requirements/jira/KAN-5/KAN-6/KAN-6_requirement.md +0 -32
- package/examples/practices/testcases/api/book_management_api_test_cases.md +0 -144
- package/examples/practices/testcases/api/user_management_api_test_cases.md +0 -139
- package/examples/practices/testcases/crm/test_cases_crm_login.md +0 -148
- package/examples/practices/testcases/crm/test_cases_customers.md +0 -156
- package/examples/pytest-api-suite/README.md +0 -45
- package/examples/pytest-api-suite/conftest.py +0 -31
- package/examples/pytest-api-suite/pages/user_api_client.py +0 -36
- package/examples/pytest-api-suite/requirements.txt +0 -2
- package/examples/pytest-api-suite/tests/test_user_api.py +0 -44
- package/examples/selenium-suite/README.md +0 -18
- package/examples/selenium-suite/pages/base_page.py +0 -27
- package/examples/selenium-suite/pages/login_page.py +0 -29
- package/examples/selenium-suite/pages/order_page.py +0 -25
- package/examples/selenium-suite/pytest.ini +0 -6
- package/examples/selenium-suite/requirements.txt +0 -2
- package/examples/selenium-suite/tests/test_login.py +0 -10
- package/examples/selenium-suite/tests/test_order.py +0 -10
package/tools/TOOLS_RUNBOOK.md
CHANGED
|
@@ -75,7 +75,17 @@
|
|
|
75
75
|
| **Cross-Platform Token & Cost Auditor (Antigravity / Cursor / Claude)** | `tools/count_tokens.py` | `python tools/count_tokens.py` (or `--platform cursor` / `--platform all --list` / `--file <path>`) |
|
|
76
76
|
| **Standalone Executive HTML Dashboard Generator** | `tools/dashboard_generator.py` | `python tools/dashboard_generator.py` (or `agent-qa dashboard [--open]`) |
|
|
77
77
|
| **Real-Time Incremental Watch Mode Sentinel** | `tools/watch_mode.py` | `python tools/watch_mode.py` (or `agent-qa watch [--once]`) |
|
|
78
|
+
| **Technical Debt & Shortcut Harvester ("debt")** | `tools/debt_harvester.py` | `agent-qa debt [path]` (or `python tools/debt_harvester.py --scan`).<br/>*Autonomous:* Scans `shortcut:` markers across repo, generates tracked markdown ledger. |
|
|
79
|
+
| **6-Pillar Senior Git Diff Reviewer ("review")** | `tools/senior_code_review.py` | `agent-qa review [--staged]` (or `python tools/senior_code_review.py`).<br/>*Autonomous:* Reviews diff across Bugs, Security, Concurrency, Missing Tests, Speed, Bloat. |
|
|
78
80
|
| **Upstream Version Check & 1-Click Self-Update** | `tools/update_sentinel.py` | `python tools/update_sentinel.py --check / --update` (or `agent-qa update` / `npx synapse-hub update`) |
|
|
81
|
+
| **Tier-2 Skill Routing & Collision Guard (Gate 9)** | `tools/skill_collision_guard.py` | `python tools/skill_collision_guard.py` (or `verify_all Gate 9` / `--route "<intent>"`) |
|
|
82
|
+
| **GoEx Reversible Sandbox Teardown Stack** | `tools/reversible_sandbox.py` | `python tools/reversible_sandbox.py run --cmd "<cmd>" --rollback "<cleanup>"` |
|
|
83
|
+
| **Multi-Trial Episodic Reflexion Loop (K=3)** | `tools/auto_heal_reflexion.py` | `python tools/auto_heal_reflexion.py --test-cmd "<cmd>" --max-trials 3` |
|
|
84
|
+
| **Voyager Lifelong Page Class SQLite Vault** | `tools/skill_vault.py` | `python tools/skill_vault.py query "<keyword>"` / `stats` / `store` |
|
|
85
|
+
| **Stanford DSPy Declarative QA Signatures** | `tools/dspy_qa_signatures.py` | `python tools/dspy_qa_signatures.py compile-suite --spec <file>` |
|
|
86
|
+
| **Pocock Grilling Primitive & Requirement Interrogation** | `tools/interview_story.py` | `python tools/interview_story.py analyze <story.md>` / `interactive` |
|
|
87
|
+
| **Mutant-Directed Textual Loss Optimizer (TextGrad)** | `tools/textgrad_mutation_optimizer.py` | `python tools/textgrad_mutation_optimizer.py optimize --test-file <path>` |
|
|
88
|
+
| **Tool Function Calling Benchmark (Gorilla BFCL)** | `tools/synapse_qa_bench.py` | `python tools/synapse_qa_bench.py benchmark --top-k 5` |
|
|
79
89
|
|
|
80
90
|
---
|
|
81
91
|
|
|
@@ -308,7 +318,7 @@ agent-qa update
|
|
|
308
318
|
|
|
309
319
|
---
|
|
310
320
|
|
|
311
|
-
###
|
|
321
|
+
### 17. `tools/omni_transpiler.py`
|
|
312
322
|
- **Purpose:** Universal Polyglot AST Engine & Cross-Framework Transpiler. Allows a single QA engineer to parse, inventory, and transpile test automation code across Java (Selenium), TypeScript (Playwright), Python, Groovy (Katalon Clean POM), and Cypress in 0 tokens without network calls or LLM hallucinations.
|
|
313
323
|
- **CLI Syntax:**
|
|
314
324
|
```bash
|
|
@@ -324,7 +334,7 @@ agent-qa update
|
|
|
324
334
|
|
|
325
335
|
---
|
|
326
336
|
|
|
327
|
-
###
|
|
337
|
+
### 18. `tools/bug_reporter.py`
|
|
328
338
|
- **Purpose:** Auto-Bug Reporter & Root Cause Analysis (RCA) Ticket Generator. Automatically distinguishes AUT bugs (server 500, JS exceptions) from test maintenance issues, distills stack traces, formats reproduction steps, and exports ready-to-paste Jira markup or GitHub Markdown.
|
|
329
339
|
- **CLI Syntax:**
|
|
330
340
|
```bash
|
|
@@ -333,7 +343,7 @@ agent-qa update
|
|
|
333
343
|
|
|
334
344
|
---
|
|
335
345
|
|
|
336
|
-
###
|
|
346
|
+
### 19. `tools/network_mock_shield.py`
|
|
337
347
|
- **Purpose:** API Network Mocking & Chaos Shield Generator. Generates zero-token route interception code and chaos fault injection (Stripe/VNPAY payment success/fail, 401/403 auth, 500 server crash, network latency) for Playwright, Cypress, and Python.
|
|
338
348
|
- **CLI Syntax:**
|
|
339
349
|
```bash
|
|
@@ -343,7 +353,7 @@ agent-qa update
|
|
|
343
353
|
|
|
344
354
|
---
|
|
345
355
|
|
|
346
|
-
###
|
|
356
|
+
### 20. `tools/smart_visual_masker.py`
|
|
347
357
|
- **Purpose:** Smart Visual Masker & Anti-Flake Engine. Eliminates 99% of false alarms in visual regression testing by disabling CSS animations, freezing SVG spinners, and masking dynamic timestamps, clocks, and avatars.
|
|
348
358
|
- **CLI Syntax:**
|
|
349
359
|
```bash
|
|
@@ -353,7 +363,7 @@ agent-qa update
|
|
|
353
363
|
|
|
354
364
|
---
|
|
355
365
|
|
|
356
|
-
###
|
|
366
|
+
### 21. `tools/ci_healing_hook.py`
|
|
357
367
|
- **Purpose:** CI/CD Silent Self-Healing Pipeline Hook. Executes inside GitHub Actions / GitLab CI when a locator fails, applies in-place auto-heal, and generates an automated Pull Request draft with diff and confidence score.
|
|
358
368
|
- **CLI Syntax:**
|
|
359
369
|
```bash
|
|
@@ -362,7 +372,7 @@ agent-qa update
|
|
|
362
372
|
|
|
363
373
|
---
|
|
364
374
|
|
|
365
|
-
###
|
|
375
|
+
### 22. `tools/export_postman_collection.py`
|
|
366
376
|
- **Purpose:** Enterprise OpenAPI/Swagger, HAR & Zero-Input Domain Postman Collection v2.1.0 Exporter (Postman Pinnacle Suite). Generates fully structured Postman collections with dynamic pre-request scripts, SLA latency tests, response code assertions, autonomous token/entity chaining, native **AJV JSON Schema Validation**, companion **Data-Driven Testing (DDT) CSV matrix**, and **Autonomous Zero-Input Domain Synthesis** (`--domain [ecommerce|banking|saas]`).
|
|
367
377
|
- **CLI Syntax:**
|
|
368
378
|
```bash
|
|
@@ -379,7 +389,7 @@ agent-qa update
|
|
|
379
389
|
|
|
380
390
|
---
|
|
381
391
|
|
|
382
|
-
###
|
|
392
|
+
### 23. `tools/generate_jmx_plan.py`
|
|
383
393
|
- **Purpose:** Apache JMeter 5.x Performance Test Plan XML (.jmx) Generator (JMeter 360° Pinnacle Suite). Ingests OpenAPI specifications, Postman Collections, or HAR recordings to output production-ready JMeter load, stress, spike, and soak test plans with HTTP Cookie & Cache Managers, CSV Data Set Config, Transaction Controllers, Pareto Traffic Shaping (`--weighted-mix`), Deep Data Correlation (CSRF regex & random dynamic selectors), JSR223 Groovy HMAC payload signers, InfluxDB live APM telemetry, PerfMon server agent monitoring, and Multi-Protocol support (HTTP, JDBC, WebSocket, gRPC, Kafka).
|
|
384
394
|
- **CLI Syntax:**
|
|
385
395
|
```bash
|
|
@@ -404,7 +414,7 @@ agent-qa update
|
|
|
404
414
|
|
|
405
415
|
---
|
|
406
416
|
|
|
407
|
-
###
|
|
417
|
+
### 24. `tools/jtl_analyzer.py`
|
|
408
418
|
- **Purpose:** Apache JMeter JTL Results Analyzer & CI/CD SLA Quality Gatekeeper. Parses `.jtl` (CSV or XML), computes statistical percentiles ($P_{50}, P_{90}, P_{95}, P_{99}$, Throughput, Error Rate), evaluates user SLA thresholds, supports server telemetry correlation (`--telemetry`), and returns deterministic exit code `0` (Pass) or `1` (Fail) to enforce quality gates in automated pipelines.
|
|
409
419
|
- **CLI Syntax:**
|
|
410
420
|
```bash
|
|
@@ -420,7 +430,7 @@ agent-qa update
|
|
|
420
430
|
|
|
421
431
|
---
|
|
422
432
|
|
|
423
|
-
###
|
|
433
|
+
### 25. `tools/author_integrity.py` (Author Provenance & Anti-Tamper Integrity Guard)
|
|
424
434
|
- **Purpose:** Cryptographic and textual provenance validator enforcing the mandatory author attribution condition of the MIT License:
|
|
425
435
|
*"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software."*
|
|
426
436
|
Protects original creator **Thįŗæ Vį» (@TeeVee998)** against unauthorized author stripping or copyright tampering across `LICENSE`, `package.json`, `README.md`, and `pyproject.toml`.
|
|
@@ -438,7 +448,7 @@ agent-qa update
|
|
|
438
448
|
|
|
439
449
|
---
|
|
440
450
|
|
|
441
|
-
###
|
|
451
|
+
### 26. `tools/md_to_xlsx.py` (Enterprise Markdown-to-Excel Converter)
|
|
442
452
|
- **Purpose:** Parses Markdown Test Case tables and converts them into professional, styled Excel workbooks (`.xlsx`) with Navy Blue headers, frozen header panes (`A2`), auto-filters, color-coded badges for Risk Level (High/Med/Low) and Priority (Critical/High/Med/Low), and multi-line wrapping.
|
|
443
453
|
- **CLI Syntax:**
|
|
444
454
|
```bash
|
|
@@ -454,7 +464,7 @@ agent-qa update
|
|
|
454
464
|
|
|
455
465
|
---
|
|
456
466
|
|
|
457
|
-
###
|
|
467
|
+
### 27. `tools/count_tokens.py` (Cross-Platform Token & Cost Auditor)
|
|
458
468
|
- **Purpose:** Audits and calculates token usage (Uncached Input, KV Cache Read, and Output/Thinking tokens) and estimated API costs across **Google Antigravity, Cursor Agent, and Claude Code**. Supports turn-by-turn breakdown, per-prompt profiling, multi-client session discovery, and cache hit rate tracking.
|
|
459
469
|
- **Trigger Condition:** On-demand after completing a task, turn, or test run to monitor context efficiency, detect token bloat, or calculate LLM cost across any supported AI client.
|
|
460
470
|
- **CLI Syntax:**
|
|
@@ -492,7 +502,7 @@ agent-qa update
|
|
|
492
502
|
|
|
493
503
|
---
|
|
494
504
|
|
|
495
|
-
###
|
|
505
|
+
### 28. `tools/dashboard_generator.py` (Standalone Executive HTML Dashboard)
|
|
496
506
|
- **Purpose:** Compiles project health metrics, 9 Quality Gates status, AST repository maps, benchmark results, and skills inventory into a single, dependency-free, modern HTML dashboard (`PROJECT_DASHBOARD.html`).
|
|
497
507
|
- **Trigger Condition:** On-demand when presenting project status to stakeholders, QA leads, or managers, or after completing project analysis/audits.
|
|
498
508
|
- **CLI Syntax:**
|
|
@@ -510,7 +520,7 @@ agent-qa update
|
|
|
510
520
|
|
|
511
521
|
---
|
|
512
522
|
|
|
513
|
-
###
|
|
523
|
+
### 29. `tools/watch_mode.py` (Real-Time Incremental Watch Mode Sentinel)
|
|
514
524
|
- **Purpose:** Continuously monitors repository files for code changes and triggers near-instant (< 100ms) incremental verification (UTF-8 No BOM, absolute machine paths, AST Meta Infer-style fake-pass checks) with an interactive terminal Heads-Up Display (HUD).
|
|
515
525
|
- **Trigger Condition:** During active test development or refactoring sessions to get immediate feedback without manually running commands.
|
|
516
526
|
- **CLI Syntax:**
|
|
@@ -525,3 +535,162 @@ agent-qa update
|
|
|
525
535
|
# 3. Run incremental scan once on all files and exit (ideal for CI/CD pre-commit hooks)
|
|
526
536
|
agent-qa watch --once
|
|
527
537
|
```
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
### 30. `tools/debt_harvester.py` (Technical Debt & Shortcut Harvester)
|
|
542
|
+
- **Purpose:** Scans code comments across multiple programming languages (`#`, `//`, `/* */`, `--`, `<!-- -->`) for `shortcut: <limit>, <when to upgrade>` annotations left by lazy senior developers, compiling them into a structured Markdown debt ledger or machine-readable JSON.
|
|
543
|
+
- **Trigger Condition:** On-demand when scanning accumulated technical debt, before major releases, or when user asks "scan debt" / "list shortcuts".
|
|
544
|
+
- **CLI Syntax:**
|
|
545
|
+
```bash
|
|
546
|
+
# 1. Scan codebase for shortcuts and display table
|
|
547
|
+
agent-qa debt
|
|
548
|
+
python3 tools/debt_harvester.py --scan
|
|
549
|
+
|
|
550
|
+
# 2. Scan specific directory and export to markdown ledger
|
|
551
|
+
agent-qa debt ./src --output DEBT_LEDGER.md
|
|
552
|
+
|
|
553
|
+
# 3. Output machine-readable JSON for CI integration
|
|
554
|
+
agent-qa debt --json
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
### 31. `tools/senior_code_review.py` (6-Pillar Senior Git Diff Reviewer)
|
|
560
|
+
- **Purpose:** Performs senior-level engineering code review on uncommitted Git diffs (or staged changes) across 6 core pillars: Bugs & Logic, Security & Boundaries, Real Concurrency & Scale, Missing Tests, Speed & Perf, and Bloat Elimination.
|
|
561
|
+
- **Trigger Condition:** On-demand before committing, submitting a PR, or when user asks "review diff" / "review code" / "senior review".
|
|
562
|
+
- **CLI Syntax:**
|
|
563
|
+
```bash
|
|
564
|
+
# 1. Review all working tree git diff changes
|
|
565
|
+
agent-qa review
|
|
566
|
+
python3 tools/senior_code_review.py
|
|
567
|
+
|
|
568
|
+
# 2. Review staged changes only
|
|
569
|
+
agent-qa review --staged
|
|
570
|
+
python3 tools/senior_code_review.py --staged
|
|
571
|
+
|
|
572
|
+
# 3. Output review report as Markdown or JSON
|
|
573
|
+
agent-qa review --output-md REVIEW_REPORT.md
|
|
574
|
+
agent-qa review --json
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
### 32. `tools/skill_collision_guard.py` (Tier-2 Skill Routing & Collision Guard ā Gate 9)
|
|
580
|
+
- **Purpose:** Enforces deterministic skill dispatch and prevents routing collision across internal Hub skills (`.agents/skills/`) and external plugins based on cosine/Jaccard semantic overlap. Guarantees zero ambiguous triggers and acts as DoD Gate 9.
|
|
581
|
+
- **Trigger Condition:** Executed automatically during `verify_all.py` (Gate 9), pre-commit, or on-demand when auditing skill trigger uniqueness.
|
|
582
|
+
- **CLI Syntax:**
|
|
583
|
+
```bash
|
|
584
|
+
# 1. Audit skill overlap and check for collision
|
|
585
|
+
python3 tools/skill_collision_guard.py
|
|
586
|
+
|
|
587
|
+
# 2. Audit with custom similarity threshold (default: 0.75 critical, 0.50 warning)
|
|
588
|
+
python3 tools/skill_collision_guard.py --threshold 0.80 --warn-threshold 0.45
|
|
589
|
+
|
|
590
|
+
# 3. Output machine-readable JSON for CI integration
|
|
591
|
+
python3 tools/skill_collision_guard.py --json
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
### 33. `tools/reversible_sandbox.py` (GoEx Reversible Teardown Sandbox Stack)
|
|
597
|
+
- **Purpose:** Manages a deterministic LIFO undo execution stack for safe test automation and self-healing. Automatically rolls back filesystem mutations, database fixture insertions, and environment changes if a test or patch crashes.
|
|
598
|
+
- **Trigger Condition:** When dispatching destructive mutations, exploratory self-healing patches, or running isolated trial runs.
|
|
599
|
+
- **CLI Syntax:**
|
|
600
|
+
```bash
|
|
601
|
+
# 1. Check current sandbox undo stack status
|
|
602
|
+
python3 tools/reversible_sandbox.py --status
|
|
603
|
+
|
|
604
|
+
# 2. Run reversible stack verification demo
|
|
605
|
+
python3 tools/reversible_sandbox.py --demo
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### 34. `tools/auto_heal_reflexion.py` (Multi-Trial Episodic Reflexion Loop ā K=3)
|
|
611
|
+
- **Purpose:** Implements the Noah Shinn Episodic Reflexion loop for failed automated tests. Performs up to $K=3$ iterative trial-feedback cycles, updating episodic memory and self-correcting locators/code without polluting git history.
|
|
612
|
+
- **Trigger Condition:** When headless test suites fail in runner, or single-pass self-healing fails to resolve complex selector or timing issues.
|
|
613
|
+
- **CLI Syntax:**
|
|
614
|
+
```bash
|
|
615
|
+
# 1. Run multi-trial reflexion self-healing on failing test
|
|
616
|
+
python3 tools/auto_heal_reflexion.py --test "TC_Checkout_01" --error "ElementClickInterceptedException"
|
|
617
|
+
|
|
618
|
+
# 2. Configure custom max trials (default: 3)
|
|
619
|
+
python3 tools/auto_heal_reflexion.py --test "TC_Login_02" --error "TimeoutException" --max-trials 5
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
### 35. `tools/skill_vault.py` (Voyager Lifelong Page Class SQLite Vault)
|
|
625
|
+
- **Purpose:** Persists, indexes, and retrieves verified Clean POM Page Class methods, custom locators, and resilient interaction primitives in a permanent SQLite repository (`~/.agent_memory/skill_vault.db`). Prevents re-inventing known solutions across sessions.
|
|
626
|
+
- **Trigger Condition:** When authoring new Page Classes, searching for proven element interactions, or archiving new successful POM patterns.
|
|
627
|
+
- **CLI Syntax:**
|
|
628
|
+
```bash
|
|
629
|
+
# 1. Query verified Page Class primitives by keyword
|
|
630
|
+
python3 tools/skill_vault.py --query "table_pagination"
|
|
631
|
+
|
|
632
|
+
# 2. List all indexed primitives in the lifelong vault
|
|
633
|
+
python3 tools/skill_vault.py --list
|
|
634
|
+
|
|
635
|
+
# 3. Seed initial baseline POM primitives
|
|
636
|
+
python3 tools/skill_vault.py --seed-samples
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
### 36. `tools/dspy_qa_signatures.py` (Stanford DSPy Declarative QA Signature Engine)
|
|
642
|
+
- **Purpose:** Transforms prompt-based test generation into typed, declarative signatures (`StoryToUniversalIR`, `HealBrokenLocator`, `MutantAssertionSignature`) with formal input/output contracts, eliminating brittle prompt hacking.
|
|
643
|
+
- **Trigger Condition:** When compiling user stories into Universal IR, generating defensive assertions, or verifying agent signature compatibility.
|
|
644
|
+
- **CLI Syntax:**
|
|
645
|
+
```bash
|
|
646
|
+
# 1. Check DSPy engine status and signature registrations
|
|
647
|
+
python3 tools/dspy_qa_signatures.py --check
|
|
648
|
+
|
|
649
|
+
# 2. Run declarative compilation demonstration
|
|
650
|
+
python3 tools/dspy_qa_signatures.py --demo
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
### 37. `tools/interview_story.py` (Pocock Grilling Primitive & Requirement Interrogation)
|
|
656
|
+
- **Purpose:** Analyzes rough user stories and acceptance criteria against the Frontier Interrogation Checklist, identifying ambiguities, missing negative boundaries, unstated auth constraints, and race conditions before coding begins.
|
|
657
|
+
- **Trigger Condition:** Triggered autonomously when a user provides an incomplete story or uses `/grill-me` to sharpen requirements.
|
|
658
|
+
- **CLI Syntax:**
|
|
659
|
+
```bash
|
|
660
|
+
# 1. Interrogate user story text directly
|
|
661
|
+
python3 tools/interview_story.py "As a user I want to checkout cart"
|
|
662
|
+
|
|
663
|
+
# 2. Analyze user story file and output JSON questions
|
|
664
|
+
python3 tools/interview_story.py docs/specs/order_flow.md --json
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
### 38. `tools/textgrad_mutation_optimizer.py` (Mutant-Directed Textual Loss Optimizer)
|
|
670
|
+
- **Purpose:** Uses AST micro-mutants as a "textual loss function" to iteratively refine test assertions and Page Class validation methods until mutation score satisfies $\ge 80\%$.
|
|
671
|
+
- **Trigger Condition:** When newly generated tests fail Gate 8 (Mutation Score $< 80\%$), optimizing assertions to catch all logic mutations.
|
|
672
|
+
- **CLI Syntax:**
|
|
673
|
+
```bash
|
|
674
|
+
# 1. Optimize test script assertions against mutants
|
|
675
|
+
python3 tools/textgrad_mutation_optimizer.py --file tests/test_checkout.py
|
|
676
|
+
|
|
677
|
+
# 2. Optimize with custom target score threshold
|
|
678
|
+
python3 tools/textgrad_mutation_optimizer.py --file tests/test_login.py --target-score 85.0
|
|
679
|
+
|
|
680
|
+
# 3. Output results as JSON
|
|
681
|
+
python3 tools/textgrad_mutation_optimizer.py --file tests/test_checkout.py --json
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
---
|
|
685
|
+
|
|
686
|
+
### 39. `tools/synapse_qa_bench.py` (Tool Function Calling Benchmark ā Gorilla BFCL)
|
|
687
|
+
- **Purpose:** Evaluates AI Agent tool-selection accuracy, argument validation precision, and multi-turn execution efficiency against standardized enterprise QA scenarios.
|
|
688
|
+
- **Trigger Condition:** On-demand when benchmarking agent model upgrades, evaluating tool prompt updates, or running QA engine evaluations.
|
|
689
|
+
- **CLI Syntax:**
|
|
690
|
+
```bash
|
|
691
|
+
# 1. Run QA function-calling benchmark across all test scenarios
|
|
692
|
+
python3 tools/synapse_qa_bench.py
|
|
693
|
+
|
|
694
|
+
# 2. Output detailed benchmark report as JSON
|
|
695
|
+
python3 tools/synapse_qa_bench.py --json
|
|
696
|
+
```
|
package/tools/__init__.py
CHANGED
package/tools/agent_canary.py
CHANGED
|
@@ -40,8 +40,8 @@ if not os.path.exists(GLOBAL_DB):
|
|
|
40
40
|
try:
|
|
41
41
|
import cache_resolver
|
|
42
42
|
cache_resolver.init_db(seed=True)
|
|
43
|
-
except Exception:
|
|
44
|
-
|
|
43
|
+
except Exception as e:
|
|
44
|
+
sys.stderr.write(f"Notice: Cache init skipped: {e}\n")
|
|
45
45
|
REPORTS_DIR = os.path.join(REPO_ROOT, "reports")
|
|
46
46
|
|
|
47
47
|
# ANSI Color codes
|
|
@@ -207,8 +207,8 @@ class DataCollisionVector(MutationVector):
|
|
|
207
207
|
conn.close()
|
|
208
208
|
if row and ("uniqueCode" in row[0] or "currentTimeMillis" in row[0]):
|
|
209
209
|
healed = True
|
|
210
|
-
except
|
|
211
|
-
|
|
210
|
+
except sqlite3.Error:
|
|
211
|
+
healed = False
|
|
212
212
|
|
|
213
213
|
if not healed:
|
|
214
214
|
hub_skills_path = os.path.join(REPO_ROOT, ".agents", "skills", "clean-pom-crafter", "SKILL.md")
|
package/tools/analyze_project.py
CHANGED
|
@@ -217,8 +217,8 @@ def run_full_analysis(target_repo):
|
|
|
217
217
|
try:
|
|
218
218
|
with open(report_in_root, "w", encoding="utf-8") as f:
|
|
219
219
|
f.write(md_content)
|
|
220
|
-
except
|
|
221
|
-
|
|
220
|
+
except OSError as e:
|
|
221
|
+
sys.stderr.write(f"Notice: Could not write root report copy: {e}\n")
|
|
222
222
|
|
|
223
223
|
print(f"\n{BOLD}{CYAN}======================================================================{RESET}")
|
|
224
224
|
print(f"{BOLD}{CYAN} EXECUTIVE ANALYSIS COMPLETE {RESET}")
|
package/tools/api_fuzzer.py
CHANGED
|
@@ -161,7 +161,7 @@ class ApiFuzzer:
|
|
|
161
161
|
return True
|
|
162
162
|
|
|
163
163
|
# 1. Exact loopback / special names
|
|
164
|
-
if host in ("localhost", "127.0.0.1", "::1", "0.0.0.0"):
|
|
164
|
+
if host in ("localhost", "127.0.0.1", "::1", "0.0.0.0"): # nosec B104
|
|
165
165
|
return True
|
|
166
166
|
|
|
167
167
|
# 2. Check IP address (loopback or private RFC 1918, disallowing link-local metadata like 169.254.169.254)
|
|
@@ -172,7 +172,7 @@ class ApiFuzzer:
|
|
|
172
172
|
return False
|
|
173
173
|
return ip.is_loopback or ip.is_private
|
|
174
174
|
except ValueError:
|
|
175
|
-
|
|
175
|
+
ip = None # host is a domain name, not an IP literal
|
|
176
176
|
|
|
177
177
|
# 3. Special-use TLDs (RFC 6761 / RFC 2606)
|
|
178
178
|
if any(host.endswith(tld) for tld in (".local", ".localhost", ".internal", ".test")):
|
|
@@ -241,7 +241,7 @@ class ApiFuzzer:
|
|
|
241
241
|
|
|
242
242
|
if self.spec_path.startswith(("http://", "https://")):
|
|
243
243
|
req = urllib.request.Request(self.spec_path, headers={"User-Agent": "AgentQA-Fuzzer/2.0"})
|
|
244
|
-
with urllib.request.urlopen(req, context=self.ssl_context, timeout=10.0) as resp:
|
|
244
|
+
with urllib.request.urlopen(req, context=self.ssl_context, timeout=10.0) as resp: # nosec B310
|
|
245
245
|
raw = resp.read().decode("utf-8")
|
|
246
246
|
return json.loads(raw)
|
|
247
247
|
else:
|
|
@@ -452,7 +452,7 @@ class ApiFuzzer:
|
|
|
452
452
|
duration_ms = 0.0
|
|
453
453
|
|
|
454
454
|
try:
|
|
455
|
-
with urllib.request.urlopen(req, context=self.ssl_context, timeout=self.timeout_sec) as resp:
|
|
455
|
+
with urllib.request.urlopen(req, context=self.ssl_context, timeout=self.timeout_sec) as resp: # nosec B310
|
|
456
456
|
status_code = resp.getcode()
|
|
457
457
|
response_body = resp.read().decode("utf-8", errors="replace")
|
|
458
458
|
except urllib.error.HTTPError as he:
|
package/tools/auto_heal.py
CHANGED
|
@@ -30,6 +30,7 @@ import pinpoint_failure
|
|
|
30
30
|
import cache_resolver
|
|
31
31
|
import project_state
|
|
32
32
|
import heuristic_locator_matcher
|
|
33
|
+
import auto_heal_reflexion
|
|
33
34
|
|
|
34
35
|
GREEN = "\033[92m"
|
|
35
36
|
RED = "\033[91m"
|
|
@@ -52,9 +53,11 @@ def diagnose_and_plan_heal(target_dir, junit_xml_path=None):
|
|
|
52
53
|
# 1. Pinpoint failure from JUnit XML or logs
|
|
53
54
|
failure_info = None
|
|
54
55
|
if junit_xml_path and os.path.exists(junit_xml_path):
|
|
55
|
-
failures = pinpoint_failure
|
|
56
|
+
failures = getattr(pinpoint_failure, "parse_failures", None) or getattr(pinpoint_failure, "parse_junit_xml", None)
|
|
56
57
|
if failures:
|
|
57
|
-
|
|
58
|
+
res = failures(junit_xml_path)
|
|
59
|
+
if res:
|
|
60
|
+
failure_info = res[0]
|
|
58
61
|
|
|
59
62
|
if not failure_info:
|
|
60
63
|
# Search for any recent report in Reports/
|
|
@@ -99,13 +102,20 @@ def diagnose_and_plan_heal(target_dir, junit_xml_path=None):
|
|
|
99
102
|
"cache_match": bool(cache_solution),
|
|
100
103
|
"heuristic_match": None,
|
|
101
104
|
"recommended_patch": None,
|
|
105
|
+
"verbal_reflection": None,
|
|
102
106
|
"episodic_lessons": [l["lesson_summary"] for l in lessons]
|
|
103
107
|
}
|
|
104
108
|
|
|
109
|
+
# 2b. Reflexion Verbal Diagnosis
|
|
110
|
+
healer = auto_heal_reflexion.ClosedLoopHealer(max_trials=3)
|
|
111
|
+
verbal_reflection = healer.generate_reflection(err_sig, "", "")
|
|
112
|
+
plan["verbal_reflection"] = verbal_reflection
|
|
113
|
+
|
|
105
114
|
if lessons:
|
|
106
115
|
print(f" {CYAN}š§ [EPISODIC REFLEXION] Top Historical Lessons for Context:{RESET}")
|
|
107
116
|
for idx, l in enumerate(lessons, 1):
|
|
108
117
|
print(f" {idx}. [{l['page_context']}]: {l['lesson_summary']}")
|
|
118
|
+
print(f" {CYAN}š” [REFLEXION DIAGNOSIS] {verbal_reflection}{RESET}")
|
|
109
119
|
|
|
110
120
|
if cache_solution:
|
|
111
121
|
print(f" {GREEN}[MATCH] Found cached resolution (Score: {cache_solution['score']:.2f}):{RESET}")
|
|
@@ -164,6 +174,8 @@ def main():
|
|
|
164
174
|
parser.add_argument("--context", default="GLOBAL", help="Page context for the recorded lesson")
|
|
165
175
|
parser.add_argument("--error", default="UnknownError", help="Error signature for the recorded lesson")
|
|
166
176
|
parser.add_argument("--fix", default="", help="Successful fix for the recorded lesson")
|
|
177
|
+
parser.add_argument("--reflexion", action="store_true", help="Execute multi-trial reflection loop (K=3)")
|
|
178
|
+
parser.add_argument("--max-trials", type=int, default=3, help="Max trials for reflexion healing loop")
|
|
167
179
|
args = parser.parse_args()
|
|
168
180
|
|
|
169
181
|
if args.record_lesson:
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# SPDX-FileCopyrightText: Copyright (c) 2026 Thįŗæ Vį» (@TeeVee998). All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
# Project: Synapse-Hub (https://github.com/TeeVee998/Synapse-Hub)
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Multi-Trial Episodic Reflexion Loop for Autonomous Healing (Noah Shinn / Reflexion Pattern)
|
|
8
|
+
------------------------------------------------------------------------------------------
|
|
9
|
+
Replaces single-shot heuristic locator healing with an iterative, multi-trial reflection
|
|
10
|
+
loop (K=3). When a test fails:
|
|
11
|
+
1. Evaluator extracts failure stacktrace & symptom.
|
|
12
|
+
2. Reflexion Generator creates a 2-line verbal diagnosis of why the patch/locator failed.
|
|
13
|
+
3. Memory Buffer accumulates trials across attempts.
|
|
14
|
+
4. Actor synthesizes the next patch conditioned on previous reflections.
|
|
15
|
+
5. Upon pass -> records to positive cache (healing_cache & lessons_learned).
|
|
16
|
+
6. Upon exhaustion of K=3 -> records to negative cache (failed_fixes) to block blind retries.
|
|
17
|
+
|
|
18
|
+
Reference:
|
|
19
|
+
- Noah Shinn et al. (Reflexion: Language Agents with Verbal Reinforcement Learning).
|
|
20
|
+
- Synapse-Hub Subsystem 2: Section 6.3 of agent_skill_training_analysis.md.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
import sys
|
|
25
|
+
import json
|
|
26
|
+
import argparse
|
|
27
|
+
from dataclasses import dataclass, asdict
|
|
28
|
+
from typing import List, Optional, Callable, Dict, Any, Tuple
|
|
29
|
+
|
|
30
|
+
# Enforce UTF-8 stdout encoding for Windows console compatibility
|
|
31
|
+
if hasattr(sys.stdout, 'reconfigure'):
|
|
32
|
+
try:
|
|
33
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
34
|
+
sys.stderr.reconfigure(encoding='utf-8')
|
|
35
|
+
except Exception:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
39
|
+
sys.path.insert(0, SCRIPT_DIR)
|
|
40
|
+
|
|
41
|
+
import cache_resolver
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class ReflexionTrial:
|
|
46
|
+
trial_number: int
|
|
47
|
+
patch_attempt: str
|
|
48
|
+
error_feedback: str
|
|
49
|
+
verbal_reflection: str
|
|
50
|
+
is_passing: bool
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ClosedLoopHealer:
|
|
54
|
+
"""Orchestrates multi-trial reflection loops for self-healing test automation."""
|
|
55
|
+
|
|
56
|
+
def __init__(self, max_trials: int = 3):
|
|
57
|
+
self.max_trials = max_trials
|
|
58
|
+
self.memory_buffer: List[ReflexionTrial] = []
|
|
59
|
+
|
|
60
|
+
def generate_reflection(self, error_sig: str, patch_attempt: str, previous_error: str) -> str:
|
|
61
|
+
"""
|
|
62
|
+
Synthesizes a structured 2-line verbal reflection explaining why the previous attempt failed
|
|
63
|
+
and prescribing the strategic adjustment for the next attempt.
|
|
64
|
+
"""
|
|
65
|
+
err_lower = (previous_error or error_sig).lower()
|
|
66
|
+
if "staleelement" in err_lower or "stale" in err_lower:
|
|
67
|
+
return "Reflection: DOM node re-rendered asynchronously after API call. Adjustment: Must wait for loader/backdrop detachment before re-querying element."
|
|
68
|
+
elif "intercepted" in err_lower or "click" in err_lower:
|
|
69
|
+
return "Reflection: Click intercepted by fading overlay/spinner animation. Adjustment: Use smart wait for overlay detachment or bypass via safe JS click."
|
|
70
|
+
elif "timeout" in err_lower or "nosuchelement" in err_lower:
|
|
71
|
+
return "Reflection: Static selector did not appear within timeout window. Adjustment: Fallback to Accessibility role/label or dynamic data-testid attribute."
|
|
72
|
+
elif "assert" in err_lower:
|
|
73
|
+
return "Reflection: Assertion condition violated actual state. Adjustment: Check if state change was asynchronous or if expected data was corrupted."
|
|
74
|
+
return f"Reflection: Patch attempt failed with '{error_sig[:80]}'. Adjustment: Re-examine live DOM tree and avoid static sleeps."
|
|
75
|
+
|
|
76
|
+
def execute_healing_loop(
|
|
77
|
+
self,
|
|
78
|
+
failing_test: str,
|
|
79
|
+
initial_error: str,
|
|
80
|
+
patch_synthesizer: Callable[[str, str, List[ReflexionTrial]], str],
|
|
81
|
+
verifier: Callable[[str, str], Tuple[bool, str]],
|
|
82
|
+
page_context: str = "GLOBAL"
|
|
83
|
+
) -> Tuple[bool, Optional[str], List[ReflexionTrial]]:
|
|
84
|
+
"""
|
|
85
|
+
Executes up to max_trials attempts.
|
|
86
|
+
Returns (is_success, winning_patch, trial_history).
|
|
87
|
+
"""
|
|
88
|
+
self.memory_buffer.clear()
|
|
89
|
+
current_error = initial_error
|
|
90
|
+
|
|
91
|
+
print(f"\nš [REFLEXION LOOP] Starting Multi-Trial Self-Healing (Max K={self.max_trials}) for '{failing_test}'...")
|
|
92
|
+
|
|
93
|
+
for t in range(1, self.max_trials + 1):
|
|
94
|
+
prev_attempt = self.memory_buffer[-1].patch_attempt if self.memory_buffer else ""
|
|
95
|
+
reflection = self.generate_reflection(initial_error, prev_attempt, current_error)
|
|
96
|
+
|
|
97
|
+
print(f"\n --- Trial {t}/{self.max_trials} ---")
|
|
98
|
+
print(f" š§ Verbal Reflection: {reflection}")
|
|
99
|
+
|
|
100
|
+
# Synthesize next patch conditioned on reflection memory
|
|
101
|
+
candidate_patch = patch_synthesizer(failing_test, reflection, self.memory_buffer)
|
|
102
|
+
print(f" š§ Candidate Patch : {candidate_patch[:100]}...")
|
|
103
|
+
|
|
104
|
+
# Verify patch in headless execution
|
|
105
|
+
is_pass, new_error = verifier(failing_test, candidate_patch)
|
|
106
|
+
|
|
107
|
+
trial = ReflexionTrial(
|
|
108
|
+
trial_number=t,
|
|
109
|
+
patch_attempt=candidate_patch,
|
|
110
|
+
error_feedback=new_error if not is_pass else "PASS",
|
|
111
|
+
verbal_reflection=reflection,
|
|
112
|
+
is_passing=is_pass
|
|
113
|
+
)
|
|
114
|
+
self.memory_buffer.append(trial)
|
|
115
|
+
|
|
116
|
+
if is_pass:
|
|
117
|
+
print(f" ā
[TRIAL {t} SUCCESS] Patch verified passing!")
|
|
118
|
+
self._record_positive_memory(page_context, initial_error, candidate_patch, reflection)
|
|
119
|
+
return True, candidate_patch, self.memory_buffer
|
|
120
|
+
else:
|
|
121
|
+
print(f" ā [TRIAL {t} FAILED] Error: {new_error[:100]}")
|
|
122
|
+
current_error = new_error
|
|
123
|
+
|
|
124
|
+
print(f"\nā ļø [REFLEXION EXHAUSTED] Failed after {self.max_trials} trials. Persisting to negative memory blacklist.")
|
|
125
|
+
self._record_negative_memory(initial_error, self.memory_buffer[-1].patch_attempt, f"Failed across {self.max_trials} multi-trial attempts")
|
|
126
|
+
return False, None, self.memory_buffer
|
|
127
|
+
|
|
128
|
+
def _record_positive_memory(self, page_context: str, error_sig: str, patch: str, reflection: str):
|
|
129
|
+
try:
|
|
130
|
+
cache_resolver.record_lesson(
|
|
131
|
+
page_context=page_context,
|
|
132
|
+
error_signature=error_sig,
|
|
133
|
+
root_cause=reflection,
|
|
134
|
+
failed_attempt="Initial failing code",
|
|
135
|
+
successful_fix=patch,
|
|
136
|
+
lesson_summary=reflection
|
|
137
|
+
)
|
|
138
|
+
except Exception as e:
|
|
139
|
+
sys.stderr.write(f"Notice: Failed to record positive memory: {e}\n")
|
|
140
|
+
|
|
141
|
+
def _record_negative_memory(self, error_sig: str, failed_patch: str, reason: str):
|
|
142
|
+
try:
|
|
143
|
+
cache_resolver.record_failed_fix(
|
|
144
|
+
error_signature=error_sig,
|
|
145
|
+
patch=failed_patch,
|
|
146
|
+
reason=reason,
|
|
147
|
+
agent_role="failure-analyst"
|
|
148
|
+
)
|
|
149
|
+
except Exception as e:
|
|
150
|
+
sys.stderr.write(f"Notice: Failed to record negative memory: {e}\n")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def main():
|
|
154
|
+
parser = argparse.ArgumentParser(description="Multi-Trial Episodic Reflexion Self-Healer")
|
|
155
|
+
parser.add_argument("--test", default="SampleTest", help="Failing test identifier")
|
|
156
|
+
parser.add_argument("--error", default="ElementClickInterceptedException", help="Initial error signature")
|
|
157
|
+
parser.add_argument("--max-trials", type=int, default=3, help="Max trials (default: 3)")
|
|
158
|
+
args = parser.parse_args()
|
|
159
|
+
|
|
160
|
+
healer = ClosedLoopHealer(max_trials=args.max_trials)
|
|
161
|
+
reflection = healer.generate_reflection(args.error, "", "")
|
|
162
|
+
print(json.dumps({
|
|
163
|
+
"test": args.test,
|
|
164
|
+
"error": args.error,
|
|
165
|
+
"max_trials": args.max_trials,
|
|
166
|
+
"initial_reflection": reflection
|
|
167
|
+
}, indent=2))
|
|
168
|
+
return 0
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if __name__ == "__main__":
|
|
172
|
+
sys.exit(main())
|