synapse-hub 2.2.4 → 2.4.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 (311) hide show
  1. package/.agents/agents/failure-analyst.md +11 -0
  2. package/.agents/agents/live-explorer.md +28 -0
  3. package/.agents/agents/orchestrator.md +20 -4
  4. package/.agents/agents/pom-crafter.md +12 -0
  5. package/.agents/agents/quality-gatekeeper.md +19 -4
  6. package/.agents/agents/test-runner.md +11 -0
  7. package/.agents/rules/communication-style.md +40 -0
  8. package/.agents/rules/context-engineering.md +23 -0
  9. package/.agents/rules/git-push-protocol.md +10 -16
  10. package/.agents/rules/graphify.md +14 -14
  11. package/.agents/rules/mandatory-playwright-live.md +29 -29
  12. package/.agents/rules/mobile_appium_rules.md +132 -0
  13. package/.agents/rules/performance_testing_rules.md +74 -0
  14. package/.agents/rules/systematic-debugging.md +6 -6
  15. package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +64 -215
  16. package/.agents/skills/agent-orchestration-multi-agent-optimize/examples/swarm_workload_config.json +12 -0
  17. package/.agents/skills/antigravity-test-sentinel/SKILL.md +3 -3
  18. package/.agents/skills/antigravity-test-sentinel/examples/dod_gate_policy.json +11 -0
  19. package/.agents/skills/api-network-mocking-interception/SKILL.md +1 -1
  20. package/.agents/skills/api-network-mocking-interception/examples/network_route_stub.json +9 -0
  21. package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +9 -9
  22. package/.agents/skills/api-spec-to-e2e-matrix/examples/sample_openapi.json +19 -0
  23. package/.agents/skills/architecture-decision-records/SKILL.md +35 -412
  24. package/.agents/skills/architecture-decision-records/examples/0001-record-architecture-decisions.md +12 -0
  25. package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +1 -1
  26. package/.agents/skills/auth-session-and-cookie-manager/examples/storage_state_sample.json +11 -0
  27. package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +80 -186
  28. package/.agents/skills/backend-load-and-stress-patterns/examples/k6_load_test_sample.js +13 -0
  29. package/.agents/skills/bats-testing-patterns/SKILL.md +1 -1
  30. package/.agents/skills/bats-testing-patterns/examples/cli_runner_test.bats +6 -0
  31. package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -614
  32. package/.agents/skills/clean-pom-crafter/SKILL.md +21 -3
  33. package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -28
  34. package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -138
  35. package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +2 -2
  36. package/.agents/skills/code-refactoring-refactor-clean/examples/refactored_page_sample.groovy +9 -0
  37. package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +5 -5
  38. package/.agents/skills/db-state-verifier-and-seeder/examples/db_fixture_seed.json +12 -0
  39. package/.agents/skills/e2e-testing-patterns/SKILL.md +1 -1
  40. package/.agents/skills/e2e-testing-patterns/examples/playwright_sharded_config.ts +12 -0
  41. package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -522
  42. package/.agents/skills/failure-autopsy-and-healing/SKILL.md +17 -3
  43. package/.agents/skills/failure-autopsy-and-healing/examples/sample_junit_failure.xml +8 -0
  44. package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -64
  45. package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -56
  46. package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -98
  47. package/.agents/skills/file-and-report-validator/SKILL.md +1 -1
  48. package/.agents/skills/file-and-report-validator/examples/sample_export_schema.json +14 -0
  49. package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +3 -3
  50. package/.agents/skills/flaky-test-sentinel-and-quarantine/examples/quarantine_registry.json +11 -0
  51. package/.agents/skills/gherkin-to-suite/SKILL.md +103 -0
  52. package/.agents/skills/gherkin-to-suite/examples/checkout.feature +39 -0
  53. package/.agents/skills/gherkin-to-suite/examples/suite_report_sample.json +334 -0
  54. package/.agents/skills/github-actions-templates/SKILL.md +47 -304
  55. package/.agents/skills/github-actions-templates/examples/matrix_test_pipeline.yml +8 -0
  56. package/.agents/skills/graphify-impact-analyzer/SKILL.md +6 -6
  57. package/.agents/skills/graphify-impact-analyzer/examples/dependency_blast_radius.json +8 -0
  58. package/.agents/skills/katalon-cli-runner/SKILL.md +2 -2
  59. package/.agents/skills/katalon-cli-runner/examples/headless_kre_exec.sh +3 -0
  60. package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -209
  61. package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -155
  62. package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -67
  63. package/.agents/skills/lam-script-generator/SKILL.md +42 -1
  64. package/.agents/skills/lam-script-generator/examples/user_story_sample.md +8 -0
  65. package/.agents/skills/lean-code-ladder/SKILL.md +83 -0
  66. package/.agents/skills/lean-code-ladder/examples/ladder_walkthrough.md +37 -0
  67. package/.agents/skills/meta-prompt-crafter/SKILL.md +107 -0
  68. package/.agents/skills/meta-prompt-crafter/examples/qa_prompt_template.md +35 -0
  69. package/.agents/skills/persistent-planning-files/SKILL.md +108 -0
  70. package/.agents/skills/persistent-planning-files/examples/task_plan_example.md +56 -0
  71. package/.agents/skills/playwright-live-interaction/SKILL.md +49 -1
  72. package/.agents/skills/playwright-live-interaction/examples/live_probe_script.js +5 -0
  73. package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -160
  74. package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -75
  75. package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -388
  76. package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -134
  77. package/.agents/skills/playwright-webapp-testing/SKILL.md +93 -0
  78. package/.agents/skills/playwright-webapp-testing/examples/server_lifecycle_playwright.py +63 -0
  79. package/.agents/skills/rbt-manual-testing/SKILL.md +150 -0
  80. package/.agents/skills/rbt-manual-testing/examples/checkout_rbt_manual_suite.md +25 -0
  81. package/.agents/skills/security-dast-sentinel/SKILL.md +54 -135
  82. package/.agents/skills/security-dast-sentinel/examples/dast_scan_config.json +10 -0
  83. package/.agents/skills/self-healing-locator/SKILL.md +24 -10
  84. package/.agents/skills/self-healing-locator/examples/aom_diff_sample.json +16 -0
  85. package/.agents/skills/skillspector-security-guard/SKILL.md +32 -90
  86. package/.agents/skills/skillspector-security-guard/examples/safe_mcp_config.json +12 -0
  87. package/.agents/skills/surgical-coding-principles/SKILL.md +89 -0
  88. package/.agents/skills/surgical-coding-principles/examples/surgical_vs_scope_creep.md +46 -0
  89. package/.agents/skills/synthetic-test-data-generator/SKILL.md +3 -3
  90. package/.agents/skills/synthetic-test-data-generator/examples/idempotent_data_recipe.json +9 -0
  91. package/.agents/skills/systematic-debugging/SKILL.md +100 -0
  92. package/.agents/skills/systematic-debugging/examples/four_phase_case.md +44 -0
  93. package/.agents/skills/test-driven-development/SKILL.md +114 -0
  94. package/.agents/skills/test-driven-development/examples/red_green_refactor_qa.md +78 -0
  95. package/.agents/skills/token-and-context-optimizer/SKILL.md +1 -1
  96. package/.agents/skills/token-and-context-optimizer/examples/distilled_log_sample.txt +3 -0
  97. package/.agents/skills/verification-before-completion/SKILL.md +100 -0
  98. package/.agents/skills/verification-before-completion/examples/evidence_log_example.md +46 -0
  99. package/.agents/skills/visual-regression-sentinel/SKILL.md +21 -1
  100. package/.agents/skills/visual-regression-sentinel/examples/visual_mask_rules.json +9 -0
  101. package/.agents/skills/wcag-audit-patterns/SKILL.md +3 -3
  102. package/.agents/skills/wcag-audit-patterns/examples/wcag_compliance_checklist.json +10 -0
  103. package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -541
  104. package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +1 -1
  105. package/.agents/skills/web-vitals-and-performance-profiler/examples/cwv_budget_policy.json +6 -0
  106. package/.agents/templates/completion_report.md +57 -57
  107. package/.agents/workflows/analyze_requirement_document.md +18 -0
  108. package/.agents/workflows/export_testcases_excel.md +32 -0
  109. package/.agents/workflows/generate_combinatorial_test_data.md +28 -0
  110. package/.agents/workflows/generate_cross_module_test_plan.md +37 -0
  111. package/.agents/workflows/generate_manual_testcases_rbt.md +56 -0
  112. package/.agents/workflows/generate_requirements_from_website.md +25 -0
  113. package/.agents/workflows/generate_testcases_from_requirements.md +21 -0
  114. package/.agents/workflows/graphify.md +10 -10
  115. package/.agents/workflows/verify.md +2 -2
  116. package/.cursor/rules/language.mdc +7 -7
  117. package/.cursor/rules/synapse-qa.mdc +23 -0
  118. package/.cursorrules +7 -0
  119. package/.pre-commit-hooks.yaml +14 -0
  120. package/.windsurfrules +7 -0
  121. package/AGENTS.md +54 -15
  122. package/CLAUDE.md +35 -12
  123. package/LICENSE +30 -0
  124. package/NOTICE +180 -0
  125. package/README.en.md +325 -0
  126. package/README.md +247 -516
  127. package/action.yml +51 -0
  128. package/benchmarks/qa_eval/README.md +71 -0
  129. package/benchmarks/qa_eval/build_dataset.py +677 -0
  130. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-06_api_contract_drift.json +22 -0
  131. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-07_api_contract_drift.json +22 -0
  132. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-08_api_contract_drift.json +22 -0
  133. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-09_api_contract_drift.json +22 -0
  134. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-10_api_contract_drift.json +22 -0
  135. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-21_fake_pass_tautology.json +21 -0
  136. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-22_fake_pass_tautology.json +21 -0
  137. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-23_fake_pass_tautology.json +21 -0
  138. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-24_fake_pass_tautology.json +21 -0
  139. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-25_fake_pass_tautology.json +21 -0
  140. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-01_locator_drift.json +23 -0
  141. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-02_locator_drift.json +23 -0
  142. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-03_locator_drift.json +23 -0
  143. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-04_locator_drift.json +23 -0
  144. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-05_locator_drift.json +23 -0
  145. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-16_stale_and_mutation.json +22 -0
  146. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-17_stale_and_mutation.json +22 -0
  147. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-18_stale_and_mutation.json +22 -0
  148. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-19_stale_and_mutation.json +22 -0
  149. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-20_stale_and_mutation.json +23 -0
  150. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-11_timing_and_race.json +22 -0
  151. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-12_timing_and_race.json +22 -0
  152. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-13_timing_and_race.json +22 -0
  153. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-14_timing_and_race.json +22 -0
  154. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-15_timing_and_race.json +22 -0
  155. package/benchmarks/qa_eval/eval_runner.py +418 -0
  156. package/benchmarks/qa_eval/reports/AB_METHODOLOGY_REPORT.md +83 -0
  157. package/benchmarks/qa_eval/reports/BENCHMARK_REPORT.md +69 -0
  158. package/benchmarks/qa_eval/reports/eval_results.json +105 -0
  159. package/bin/agent-qa.js +10 -3
  160. package/docs/ARCHITECTURE.md +107 -0
  161. package/docs/CI_CD_INTEGRATION.md +94 -0
  162. package/docs/CLI_REFERENCE.md +157 -0
  163. package/docs/CONTRIBUTING.md +91 -0
  164. package/docs/PLUGIN_DEVELOPMENT_GUIDE.md +126 -0
  165. package/docs/TOKEN_QUOTA_PLAYBOOK.md +41 -0
  166. package/docs/adopted-ecosystem-tools.md +87 -0
  167. package/docs/schemas/synapse.config.schema.json +64 -0
  168. package/examples/cypress-ecommerce-suite/README.md +45 -0
  169. package/examples/cypress-ecommerce-suite/cypress/e2e/checkout.cy.js +17 -0
  170. package/examples/cypress-ecommerce-suite/cypress/pages/BasePage.js +29 -0
  171. package/examples/cypress-ecommerce-suite/cypress/pages/CartPage.js +51 -0
  172. package/examples/cypress-ecommerce-suite/cypress.config.js +13 -0
  173. package/examples/cypress-ecommerce-suite/package.json +13 -0
  174. package/examples/katalon-suite/Keywords/pages/BasePage.groovy +19 -0
  175. package/examples/katalon-suite/Keywords/pages/DashboardPage.groovy +29 -0
  176. package/examples/katalon-suite/Keywords/pages/LoginPage.groovy +45 -0
  177. package/examples/katalon-suite/Profiles/default.glbl +12 -0
  178. package/examples/katalon-suite/README.md +18 -0
  179. package/examples/katalon-suite/Scripts/Auth/TC_LoginSuccess/Script1234567890.groovy +12 -0
  180. package/examples/katalon-suite/Scripts/Dashboard/TC_ViewSummary/Script1234567891.groovy +15 -0
  181. package/examples/katalon-suite/katalon_suite.prj +21 -0
  182. package/examples/playwright-crm-suite/README.md +40 -0
  183. package/examples/playwright-crm-suite/package.json +14 -0
  184. package/examples/playwright-crm-suite/pages/BasePage.ts +37 -0
  185. package/examples/playwright-crm-suite/pages/CustomerPage.ts +57 -0
  186. package/examples/playwright-crm-suite/pages/LoginPage.ts +32 -0
  187. package/examples/playwright-crm-suite/playwright.config.ts +27 -0
  188. package/examples/playwright-crm-suite/tests/auth.spec.ts +22 -0
  189. package/examples/playwright-crm-suite/tests/customers.spec.ts +33 -0
  190. package/examples/plugins/sample-custom-plugin/README.md +14 -0
  191. package/examples/plugins/sample-custom-plugin/plugin.json +16 -0
  192. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/SKILL.md +29 -0
  193. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/examples/audit_fixture.json +8 -0
  194. package/examples/plugins/sample-custom-plugin/tools/custom_security_headers.py +125 -0
  195. package/examples/practices/README.md +22 -0
  196. package/examples/practices/requirements/crm/requirements_contracts.md +292 -0
  197. package/examples/practices/requirements/crm/requirements_customers.md +462 -0
  198. package/examples/practices/requirements/crm/requirements_login.md +202 -0
  199. package/examples/practices/requirements/crm/requirements_projects.md +396 -0
  200. package/examples/practices/requirements/crm/requirements_tasks.md +343 -0
  201. package/examples/practices/requirements/ecommerce/requirements_category_brand.txt +402 -0
  202. package/examples/practices/requirements/jira/KAN-5/KAN-1/2026-04-03_04-28-27.png +0 -0
  203. package/examples/practices/requirements/jira/KAN-5/KAN-1/KAN-1_requirement.md +52 -0
  204. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-19.png +0 -0
  205. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-57.png +0 -0
  206. package/examples/practices/requirements/jira/KAN-5/KAN-4/KAN-4_requirement.md +119 -0
  207. package/examples/practices/requirements/jira/KAN-5/KAN-5_overview.md +9 -0
  208. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-08.png +0 -0
  209. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-23.png +0 -0
  210. package/examples/practices/requirements/jira/KAN-5/KAN-6/KAN-6_requirement.md +32 -0
  211. package/examples/practices/testcases/api/book_management_api_test_cases.md +144 -0
  212. package/examples/practices/testcases/api/user_management_api_test_cases.md +139 -0
  213. package/examples/practices/testcases/crm/test_cases_crm_login.md +148 -0
  214. package/examples/practices/testcases/crm/test_cases_customers.md +156 -0
  215. package/examples/pytest-api-suite/README.md +45 -0
  216. package/examples/pytest-api-suite/conftest.py +31 -0
  217. package/examples/pytest-api-suite/pages/user_api_client.py +36 -0
  218. package/examples/pytest-api-suite/requirements.txt +2 -0
  219. package/examples/pytest-api-suite/tests/test_user_api.py +44 -0
  220. package/examples/selenium-suite/README.md +18 -0
  221. package/examples/selenium-suite/pages/base_page.py +27 -0
  222. package/examples/selenium-suite/pages/login_page.py +29 -0
  223. package/examples/selenium-suite/pages/order_page.py +25 -0
  224. package/examples/selenium-suite/pytest.ini +6 -0
  225. package/examples/selenium-suite/requirements.txt +2 -0
  226. package/examples/selenium-suite/tests/test_login.py +10 -0
  227. package/examples/selenium-suite/tests/test_order.py +10 -0
  228. package/package.json +22 -7
  229. package/scripts/generate_skill_examples.py +244 -0
  230. package/scripts/install.ps1 +112 -0
  231. package/scripts/install_global_plugin.ps1 +94 -0
  232. package/scripts/install_global_plugin.sh +49 -0
  233. package/scripts/lint_skills.ps1 +57 -0
  234. package/scripts/package_dist.py +323 -0
  235. package/scripts/setup.sh +59 -0
  236. package/scripts/update_hub.ps1 +19 -0
  237. package/scripts/update_hub.sh +15 -0
  238. package/skills_manifest.json +209 -6
  239. package/synapse.config.json +30 -0
  240. package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +7 -7
  241. package/templates/PROJECT_STATE_TEMPLATE.md +1 -1
  242. package/templates/ai_bridges/CLAUDE.md +33 -16
  243. package/templates/ai_bridges/copilot-instructions.md +14 -21
  244. package/templates/ai_bridges/cursor_synapse_qa.mdc +17 -20
  245. package/templates/ai_bridges/windsurfrules +21 -21
  246. package/templates/ci/github-actions-synapse.yml +71 -4
  247. package/templates/welcome.html.tmpl +1674 -0
  248. package/tools/.infer_baseline.json +1102 -0
  249. package/tools/TOOLS_RUNBOOK.md +92 -130
  250. package/tools/__init__.py +26 -0
  251. package/tools/agent_canary.py +501 -501
  252. package/tools/analyze_project.py +31 -17
  253. package/tools/api_fuzzer.py +278 -6
  254. package/tools/author_integrity.py +6 -6
  255. package/tools/auto_heal.py +1 -1
  256. package/tools/browser_helpers.js +105 -7
  257. package/tools/bug_reporter.py +31 -1
  258. package/tools/bump_version.py +23 -3
  259. package/tools/cache_resolver.py +248 -14
  260. package/tools/check_env.py +55 -14
  261. package/tools/check_version_sync.py +153 -0
  262. package/tools/ci_healing_hook.py +1 -1
  263. package/tools/cli.py +263 -13
  264. package/tools/count_tokens.py +1257 -0
  265. package/tools/dashboard_generator.py +2638 -0
  266. package/tools/db_sandbox.py +198 -20
  267. package/tools/e2e_flow_prober.ps1 +12 -64
  268. package/tools/e2e_flow_prober.py +99 -0
  269. package/tools/e2e_flow_prober.sh +4 -0
  270. package/tools/flaky_detector.py +4 -3
  271. package/tools/generate_allure_report.ps1 +12 -29
  272. package/tools/generate_allure_report.py +77 -0
  273. package/tools/generate_allure_report.sh +4 -0
  274. package/tools/generate_jmx_plan.py +257 -58
  275. package/tools/generate_test_reports.ps1 +12 -134
  276. package/tools/generate_test_reports.py +133 -0
  277. package/tools/generate_test_reports.sh +4 -0
  278. package/tools/gherkin_suite.py +758 -0
  279. package/tools/git_pre_commit_guard.py +12 -6
  280. package/tools/goldfish_review.py +366 -0
  281. package/tools/heal_pr_automator.py +1 -1
  282. package/tools/heuristic_locator_matcher.py +170 -21
  283. package/tools/infer_linter.py +612 -70
  284. package/tools/lint_ai_docs.py +64 -0
  285. package/tools/matrix_sharder.py +1 -1
  286. package/tools/mcp_excel_server.ps1 +12 -250
  287. package/tools/mcp_excel_server.py +249 -0
  288. package/tools/mcp_excel_server.sh +4 -0
  289. package/tools/mcp_server.py +368 -144
  290. package/tools/md_to_xlsx.py +307 -0
  291. package/tools/micro_mutator.py +300 -69
  292. package/tools/omni_transpiler.py +2 -2
  293. package/tools/output_formatter.py +128 -0
  294. package/tools/pinpoint_failure.py +88 -88
  295. package/tools/project_state.py +2 -2
  296. package/tools/repo_map.py +1 -1
  297. package/tools/safety_firewall.py +196 -45
  298. package/tools/setup_project.py +294 -30
  299. package/tools/spec_drift_sentinel.py +439 -0
  300. package/tools/sync_agent_rules.py +248 -0
  301. package/tools/telemetry_correlator.py +45 -0
  302. package/tools/test_impact.py +51 -12
  303. package/tools/tms_sync_bridge.py +21 -5
  304. package/tools/universal_ir.py +3 -0
  305. package/tools/update_sentinel.py +87 -15
  306. package/tools/verify_all.ps1 +13 -0
  307. package/tools/verify_all.py +463 -79
  308. package/tools/visual_diff_canvas.py +1 -0
  309. package/tools/visual_som_helper.py +1 -1
  310. package/tools/watch_mode.py +305 -0
  311. package/tools/welcome_page.py +291 -0
@@ -219,6 +219,12 @@ def run_correlation_analysis(
219
219
  "db_pool_correlation": round(corr_db, 3),
220
220
  "disk_correlation": round(corr_disk, 3)
221
221
  },
222
+ "otel_metrics": {
223
+ "http.server.request.duration.p95_ms": round(max_p95, 2),
224
+ "system.cpu.utilization_ratio": round(max_cpu / 100.0, 4),
225
+ "system.memory.utilization_ratio": round(max_mem / 100.0, 4),
226
+ "system.db_pool.utilization_ratio": round(max_db / 100.0, 4),
227
+ },
222
228
  "root_causes": root_causes
223
229
  }
224
230
 
@@ -274,6 +280,7 @@ def main():
274
280
  parser.add_argument("--server-metrics", "-s", help="Path to Server Telemetry CSV (timestamp, cpu_pct, memory_pct, db_pool_pct).")
275
281
  parser.add_argument("--markdown", "-m", help="Path to export Markdown RCA report.")
276
282
  parser.add_argument("--json", "-j", help="Path to export structured JSON diagnostics.")
283
+ parser.add_argument("--otel", action="store_true", help="Export OpenTelemetry ResourceMetrics payload format.")
277
284
  parser.add_argument("--sample", action="store_true", help="Generate synthetic client & server telemetry dataset for verification.")
278
285
 
279
286
  args = parser.parse_args()
@@ -333,6 +340,44 @@ def main():
333
340
  print(f" 👉 Recommendation: {c['recommendation']}")
334
341
  print("=" * 80 + "\n")
335
342
 
343
+ if args.otel:
344
+ otel_metrics = {
345
+ "resourceMetrics": [
346
+ {
347
+ "resource": {
348
+ "attributes": [
349
+ {"key": "service.name", "value": {"stringValue": "synapse-backend-under-test"}},
350
+ {"key": "telemetry.sdk.name", "value": {"stringValue": "synapse-correlator"}},
351
+ ]
352
+ },
353
+ "scopeMetrics": [
354
+ {
355
+ "scope": {"name": "synapse.telemetry.correlator", "version": "1.0.0"},
356
+ "metrics": [
357
+ {
358
+ "name": "http.server.request.duration",
359
+ "unit": "ms",
360
+ "gauge": {"dataPoints": [{"value": analysis["metrics_summary"]["max_p95_ms"]}]}
361
+ },
362
+ {
363
+ "name": "system.cpu.utilization",
364
+ "unit": "1",
365
+ "gauge": {"dataPoints": [{"value": round(analysis["metrics_summary"]["max_cpu_pct"] / 100.0, 4)}]}
366
+ },
367
+ {
368
+ "name": "system.memory.utilization",
369
+ "unit": "1",
370
+ "gauge": {"dataPoints": [{"value": round(analysis["metrics_summary"]["max_memory_pct"] / 100.0, 4)}]}
371
+ },
372
+ ]
373
+ }
374
+ ]
375
+ }
376
+ ]
377
+ }
378
+ print(json.dumps(otel_metrics, indent=2))
379
+ return
380
+
336
381
  if args.markdown:
337
382
  md = format_rca_markdown(analysis)
338
383
  os.makedirs(os.path.dirname(os.path.abspath(args.markdown)) or ".", exist_ok=True)
@@ -16,6 +16,7 @@ import os
16
16
  import sys
17
17
  import json
18
18
  import glob
19
+ import re
19
20
  import argparse
20
21
  import subprocess
21
22
 
@@ -84,7 +85,7 @@ def build_fallback_graph(repo_root):
84
85
  with open(f, "r", encoding="utf-8", errors="ignore") as fp:
85
86
  content = fp.read()
86
87
  for other_cls in class_map:
87
- if other_cls != cls_name and other_cls in content:
88
+ if other_cls != cls_name and re.search(r"\b" + re.escape(other_cls) + r"\b", content):
88
89
  edges.append({"source": cls_name, "target": other_cls})
89
90
  except Exception:
90
91
  pass
@@ -112,7 +113,9 @@ def build_fallback_graph(repo_root):
112
113
  with open(f, "r", encoding="utf-8", errors="ignore") as fp:
113
114
  content = fp.read()
114
115
  for cls_name in class_map:
115
- if cls_name in content:
116
+ # Word-boundary match: "BorrowPage" must not hit inside
117
+ # "ApprovalBorrowPage" (substring match over-counted).
118
+ if re.search(r"\b" + re.escape(cls_name) + r"\b", content):
116
119
  edges.append({"source": rel_path, "target": cls_name})
117
120
  except Exception:
118
121
  pass
@@ -120,20 +123,48 @@ def build_fallback_graph(repo_root):
120
123
  return {"nodes": nodes, "edges": edges}
121
124
 
122
125
 
126
+ def merge_graphs(primary, fallback):
127
+ """Unions two graph dicts (nodes by id, edges by (source, target)).
128
+
129
+ The Graphify graph can silently miss edges (its Groovy extractor fails on
130
+ GString/closure-heavy files), so the grep-based fallback graph is always
131
+ merged in. Over-inclusion is the safe direction for impact analysis.
132
+ """
133
+ merged = {"nodes": [], "edges": []}
134
+ seen_nodes, seen_edges = set(), set()
135
+ for node in list(primary.get("nodes", [])) + list(fallback.get("nodes", [])):
136
+ node_id = node.get("id")
137
+ if node_id and node_id not in seen_nodes:
138
+ seen_nodes.add(node_id)
139
+ merged["nodes"].append(node)
140
+ for edge in list(primary.get("edges", [])) + list(fallback.get("edges", [])):
141
+ key = (edge.get("source"), edge.get("target"))
142
+ if key not in seen_edges:
143
+ seen_edges.add(key)
144
+ merged["edges"].append(edge)
145
+ return merged
146
+
147
+
123
148
  def load_graph(repo_root=None):
124
149
  root = repo_root or HUB_ROOT
150
+ graph_data = None
125
151
  graph_path = os.path.join(root, "graphify-out", "graph.json")
126
152
  if os.path.exists(graph_path):
127
153
  with open(graph_path, "r", encoding="utf-8") as fp:
128
- return json.load(fp)
129
-
130
- hub_graph = os.path.join(HUB_ROOT, "graphify-out", "graph.json")
131
- if os.path.exists(hub_graph):
132
- with open(hub_graph, "r", encoding="utf-8") as fp:
133
- return json.load(fp)
134
-
135
- # Dynamic fallback graph
136
- return build_fallback_graph(root)
154
+ graph_data = json.load(fp)
155
+ else:
156
+ hub_graph = os.path.join(HUB_ROOT, "graphify-out", "graph.json")
157
+ if os.path.exists(hub_graph):
158
+ with open(hub_graph, "r", encoding="utf-8") as fp:
159
+ graph_data = json.load(fp)
160
+
161
+ # Always union the ground-truth fallback graph: when the target repo has a
162
+ # (possibly incomplete) graphify-out/graph.json the grep scan below is the
163
+ # only thing guaranteeing script->class edges actually exist.
164
+ fallback = build_fallback_graph(root)
165
+ if graph_data is None:
166
+ return fallback
167
+ return merge_graphs(graph_data, fallback)
137
168
 
138
169
 
139
170
  def get_git_modified_files(repo_root=None):
@@ -175,7 +206,15 @@ def get_total_test_cases(workspace_dir=None, graph_data=None, override_total=Non
175
206
  for pat in test_patterns:
176
207
  files.update(glob.glob(pat, recursive=True))
177
208
  if files:
178
- return len(files)
209
+ # Katalon-style repos list one TC twice (Scripts/<TC_x>/ScriptN.groovy
210
+ # AND Test Cases/.../TC_x.tc) — dedupe by the TC identifier so the
211
+ # denominator counts logical test cases, not file copies.
212
+ identities = set()
213
+ for f in files:
214
+ rel = os.path.relpath(f, root).replace("\\", "/")
215
+ match = re.search(r"TC[_-]\d+", rel)
216
+ identities.add(("tc", match.group(0)) if match else ("file", rel))
217
+ return len(identities)
179
218
 
180
219
  # 2. Count test case nodes in graph if available
181
220
  if graph_data and "nodes" in graph_data:
@@ -44,10 +44,21 @@ class TMSBridge:
44
44
 
45
45
  def __init__(self, provider: str = "jira", base_url: str = "", api_token: str = "", user_email: str = ""):
46
46
  self.provider = provider.lower()
47
- self.base_url = base_url or os.getenv("JIRA_URL") or os.getenv("TESTRAIL_URL") or "https://mock-alm.enterprise.local"
48
- self.api_token = api_token or os.getenv("JIRA_API_TOKEN") or os.getenv("TESTRAIL_API_KEY") or "mock_token_12345"
49
- self.user_email = user_email or os.getenv("JIRA_USER_EMAIL") or "qa-agent@enterprise.local"
50
- self.is_mock = "mock" in self.base_url or not os.getenv("JIRA_URL")
47
+ resolved_url = base_url or os.getenv("JIRA_URL") or os.getenv("TESTRAIL_URL") or ""
48
+ resolved_token = api_token or os.getenv("JIRA_API_TOKEN") or os.getenv("TESTRAIL_API_KEY") or ""
49
+ resolved_email = user_email or os.getenv("JIRA_USER_EMAIL") or ""
50
+
51
+ # Only use mock simulation if URL is omitted, mock is specified, or token is absent
52
+ if not resolved_url or "mock" in resolved_url or not resolved_token:
53
+ self.base_url = "https://mock-alm.enterprise.local"
54
+ self.api_token = "mock_token_12345"
55
+ self.user_email = resolved_email or "qa-agent@enterprise.local"
56
+ self.is_mock = True
57
+ else:
58
+ self.base_url = resolved_url
59
+ self.api_token = resolved_token
60
+ self.user_email = resolved_email
61
+ self.is_mock = False
51
62
 
52
63
  # -------------------------------------------------------------------------
53
64
  # 1. PULL MODE: Extract User Story & Acceptance Criteria
@@ -173,12 +184,17 @@ class TMSBridge:
173
184
  "timestamp": datetime.now().isoformat()
174
185
  },
175
186
  "status": "Created",
176
- "mode": "MOCK_SIMULATION" if self.is_mock else "LIVE_JIRA"
187
+ "mode": "MOCK_SIMULATION" if self.is_mock else f"LIVE_{self.provider.upper()}"
177
188
  }
178
189
 
179
190
  if self.is_mock:
180
191
  return ticket_payload
181
192
 
193
+ if self.provider != "jira":
194
+ raise NotImplementedError(
195
+ f"TMS provider '{self.provider}' is not implemented yet. Supported live provider: 'jira'."
196
+ )
197
+
182
198
  # Live Jira Bug Creation
183
199
  try:
184
200
  import urllib.request
@@ -271,6 +271,9 @@ class PageClassIR:
271
271
 
272
272
  @dataclass
273
273
  class TestCaseIR:
274
+ # IR model, not a pytest test class - prefix "Test" must not trigger collection.
275
+ __test__ = False
276
+
274
277
  id: str
275
278
  title: str
276
279
  steps: List[StepIR] = field(default_factory=list)
@@ -65,8 +65,8 @@ def get_local_version():
65
65
  try:
66
66
  with open(pkg_file, "r", encoding="utf-8") as f:
67
67
  data = json.load(f)
68
- return data.get("version", "2.1.1")
69
- except Exception:
68
+ return data.get("version", "2.3.0")
69
+ except (OSError, json.JSONDecodeError):
70
70
  pass
71
71
 
72
72
  manifest_file = os.path.join(HUB_ROOT, "skills_manifest.json")
@@ -74,11 +74,11 @@ def get_local_version():
74
74
  try:
75
75
  with open(manifest_file, "r", encoding="utf-8") as f:
76
76
  data = json.load(f)
77
- return data.get("version", "2.1.1")
78
- except Exception:
77
+ return data.get("version", "2.3.0")
78
+ except (OSError, json.JSONDecodeError):
79
79
  pass
80
80
 
81
- return "2.1.1"
81
+ return "2.3.0"
82
82
 
83
83
 
84
84
  def fetch_remote_version():
@@ -92,7 +92,7 @@ def fetch_remote_version():
92
92
  data = json.loads(resp.read().decode("utf-8"))
93
93
  if "version" in data:
94
94
  return data["version"], "npm"
95
- except Exception:
95
+ except (urllib.error.URLError, TimeoutError, OSError, json.JSONDecodeError, KeyError):
96
96
  pass
97
97
 
98
98
  # 2. Secondary fallback: GitHub raw package.json
@@ -103,7 +103,7 @@ def fetch_remote_version():
103
103
  data = json.loads(resp.read().decode("utf-8"))
104
104
  if "version" in data:
105
105
  return data["version"], "github"
106
- except Exception:
106
+ except (urllib.error.URLError, TimeoutError, OSError, json.JSONDecodeError, KeyError):
107
107
  pass
108
108
 
109
109
  return None, None
@@ -114,7 +114,7 @@ def read_update_cache():
114
114
  try:
115
115
  with open(CACHE_FILE, "r", encoding="utf-8") as f:
116
116
  return json.load(f)
117
- except Exception:
117
+ except (OSError, json.JSONDecodeError):
118
118
  pass
119
119
  return {}
120
120
 
@@ -124,7 +124,7 @@ def write_update_cache(data):
124
124
  os.makedirs(GLOBAL_DIR, exist_ok=True)
125
125
  with open(CACHE_FILE, "w", encoding="utf-8") as f:
126
126
  json.dump(data, f, indent=2)
127
- except Exception:
127
+ except OSError:
128
128
  pass
129
129
 
130
130
 
@@ -132,7 +132,16 @@ def check_for_updates(force=False, notify=True):
132
132
  """
133
133
  Checks if a newer version exists upstream.
134
134
  Uses a 24-hour file cache to prevent network overhead during daily workflows.
135
+ Air-gapped offline guard: strictly bypasses all network checks when AGENT_QA_OFFLINE is set.
135
136
  """
137
+ if (
138
+ os.environ.get("AGENT_QA_OFFLINE") in ("1", "true", "TRUE")
139
+ or os.environ.get("SYNAPSE_OFFLINE") in ("1", "true", "TRUE")
140
+ or os.environ.get("CI") in ("1", "true", "TRUE")
141
+ or os.environ.get("GITHUB_ACTIONS")
142
+ ):
143
+ return False, get_local_version(), None
144
+
136
145
  cache = read_update_cache()
137
146
  now = time.time()
138
147
  last_check = cache.get("last_check_timestamp", 0)
@@ -177,6 +186,54 @@ def print_update_banner(local_ver, remote_ver):
177
186
  print(banner)
178
187
 
179
188
 
189
+ def _is_trusted_remote(cwd):
190
+ """Verifies that git remote origin points to official Synapse Hub repository."""
191
+ try:
192
+ res = subprocess.run(
193
+ ["git", "remote", "get-url", "origin"],
194
+ cwd=cwd,
195
+ stdout=subprocess.PIPE,
196
+ stderr=subprocess.PIPE,
197
+ text=True,
198
+ timeout=3.0
199
+ )
200
+ if res.returncode == 0:
201
+ url = res.stdout.strip().lower()
202
+ return "github.com/teevee998/synapse-hub" in url or "github.com/teevee998/agent-skills" in url
203
+ except (subprocess.SubprocessError, OSError):
204
+ pass
205
+ return False
206
+
207
+
208
+ def verify_git_provenance(cwd):
209
+ """
210
+ Supply-chain security guard: Verifies that commits pulled into the agent environment
211
+ originate from trusted upstream and do not contain forged signatures.
212
+ """
213
+ if not _is_trusted_remote(cwd):
214
+ return True, "Local or fork repository (trusted upstream check bypassed)"
215
+ try:
216
+ res = subprocess.run(
217
+ ["git", "log", "-1", "--format=%H %G? %an"],
218
+ cwd=cwd,
219
+ stdout=subprocess.PIPE,
220
+ stderr=subprocess.PIPE,
221
+ text=True,
222
+ timeout=3.0
223
+ )
224
+ if res.returncode == 0:
225
+ parts = res.stdout.strip().split()
226
+ commit_sha = parts[0] if parts else "unknown"
227
+ sig_status = parts[1] if len(parts) > 1 else "N"
228
+ author = " ".join(parts[2:]) if len(parts) > 2 else "Unknown"
229
+ if sig_status == "B":
230
+ return False, f"Cryptographic integrity alert: Bad/forged signature on commit {commit_sha[:8]}"
231
+ return True, f"Verified commit {commit_sha[:8]} by {author} (sig: {sig_status})"
232
+ except Exception as e:
233
+ return False, str(e)
234
+ return True, "Provenance verified"
235
+
236
+
180
237
  def perform_update():
181
238
  """
182
239
  Executes 1-click update:
@@ -212,13 +269,27 @@ def perform_update():
212
269
  cwd=HUB_ROOT,
213
270
  stdout=subprocess.PIPE,
214
271
  stderr=subprocess.PIPE,
215
- text=True
272
+ text=True,
273
+ timeout=30.0
216
274
  )
217
275
  if res.returncode == 0:
218
276
  print(f" {GREEN}[OK] Git pull successful:{RESET}")
219
277
  for line in res.stdout.strip().splitlines():
220
278
  print(f" {line}")
279
+ ok, msg = verify_git_provenance(HUB_ROOT)
280
+ if not ok:
281
+ print(f" {RED}⚠️ Provenance Warning: {msg}{RESET}")
282
+ else:
283
+ print(f" {GREEN}[OK] {msg}{RESET}")
221
284
  updated = True
285
+ # If this is the first pull, show the welcome landing page
286
+ try:
287
+ import welcome_page
288
+ if welcome_page.is_first_run(HUB_ROOT):
289
+ welcome_page.generate_welcome_page(target_repo=HUB_ROOT, open_browser=True)
290
+ welcome_page.mark_first_run_completed(HUB_ROOT)
291
+ except (ImportError, OSError):
292
+ pass
222
293
  else:
223
294
  print(f" ⚠️ Git pull notice: {res.stderr.strip() or res.stdout.strip()}")
224
295
  except Exception as e:
@@ -230,12 +301,13 @@ def perform_update():
230
301
  ["npm", "install", "-g", "synapse-hub@latest"],
231
302
  stdout=subprocess.PIPE,
232
303
  stderr=subprocess.PIPE,
233
- text=True
304
+ text=True,
305
+ timeout=60.0
234
306
  )
235
307
  if res.returncode == 0:
236
308
  print(f" {GREEN}[OK] Global NPM package updated to latest!{RESET}")
237
309
  updated = True
238
- except Exception:
310
+ except (subprocess.SubprocessError, OSError):
239
311
  pass
240
312
 
241
313
  # 2. Check Global Plugin
@@ -244,9 +316,9 @@ def perform_update():
244
316
  plugin_git = os.path.join(GLOBAL_PLUGIN_DIR, ".git")
245
317
  if os.path.exists(plugin_git):
246
318
  try:
247
- subprocess.run(["git", "pull", "--ff-only"], cwd=GLOBAL_PLUGIN_DIR, stdout=subprocess.DEVNULL)
319
+ subprocess.run(["git", "pull", "--ff-only"], cwd=GLOBAL_PLUGIN_DIR, stdout=subprocess.DEVNULL, timeout=30.0)
248
320
  print(f" {GREEN}[OK] Updated Global Plugin repository: {GLOBAL_PLUGIN_DIR}{RESET}")
249
- except Exception:
321
+ except (subprocess.SubprocessError, OSError):
250
322
  pass
251
323
  else:
252
324
  # Refresh plugin.json in global plugin
@@ -257,7 +329,7 @@ def perform_update():
257
329
  if os.path.exists(src_pkg):
258
330
  shutil.copy2(src_pkg, dst_pkg)
259
331
  print(f" {GREEN}[OK] Refreshed plugin.json in: {GLOBAL_PLUGIN_DIR}{RESET}")
260
- except Exception:
332
+ except OSError:
261
333
  pass
262
334
 
263
335
  # 3. Re-initialize SQLite Memory Cache
@@ -0,0 +1,13 @@
1
+ # Enterprise Single-Command DoD Verification Wrapper (Windows PowerShell)
2
+ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
3
+ $pythonCmd = Get-Command python -ErrorAction SilentlyContinue
4
+ if (-not $pythonCmd) { $pythonCmd = Get-Command py -ErrorAction SilentlyContinue }
5
+ if (-not $pythonCmd) { $pythonCmd = Get-Command python3 -ErrorAction SilentlyContinue }
6
+
7
+ if ($pythonCmd) {
8
+ & $pythonCmd.Source "$scriptDir\verify_all.py" $args
9
+ exit $LASTEXITCODE
10
+ } else {
11
+ Write-Error "Python 3 is required to run verify_all. Please install Python from https://python.org"
12
+ exit 1
13
+ }