synapse-hub 2.4.3 → 2.5.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 (166) hide show
  1. package/.agents/agents/orchestrator.md +1 -0
  2. package/.agents/agents/pom-crafter.md +1 -0
  3. package/.agents/agents/quality-gatekeeper.md +6 -0
  4. package/.agents/rules/skill-precedence.md +38 -18
  5. package/.agents/rules/systematic-debugging.md +2 -0
  6. package/.agents/skills/lean-code-ladder/SKILL.md +12 -1
  7. package/.agents/skills/lean-impact-scoreboard/SKILL.md +48 -0
  8. package/.agents/skills/lean-impact-scoreboard/examples/sample_benchmark_gain.md +20 -0
  9. package/.agents/skills/lean-impact-scoreboard/examples/sample_scoreboard.md +15 -0
  10. package/.agents/skills/repo-quality-audit/SKILL.md +68 -0
  11. package/.agents/skills/repo-quality-audit/examples/sample_audit_walkthrough.md +15 -0
  12. package/.agents/skills/repo-quality-audit/examples/sample_repo_audit.md +33 -0
  13. package/.agents/skills/senior-code-review/SKILL.md +90 -0
  14. package/.agents/skills/senior-code-review/examples/sample_review_walkthrough.md +29 -0
  15. package/.agents/skills/technical-debt-harvester/SKILL.md +70 -0
  16. package/.agents/skills/technical-debt-harvester/examples/sample_debt_ledger.md +25 -0
  17. package/.agents/skills/technical-debt-harvester/examples/sample_ledger_output.md +20 -0
  18. package/.cursor/rules/synapse-qa.mdc +4 -3
  19. package/.cursorrules +1 -0
  20. package/.windsurfrules +1 -0
  21. package/AGENTS.md +51 -179
  22. package/CLAUDE.md +5 -0
  23. package/README.en.md +12 -8
  24. package/README.md +12 -8
  25. package/bin/agent-qa.js +3 -2
  26. package/docs/ARCHITECTURE.md +3 -3
  27. package/docs/CLI_REFERENCE.md +15 -1
  28. package/package.json +1 -3
  29. package/skills_manifest.json +38 -2
  30. package/synapse.config.json +1 -1
  31. package/templates/ai_bridges/CLAUDE.md +5 -0
  32. package/templates/ai_bridges/copilot-instructions.md +2 -0
  33. package/templates/ai_bridges/cursor_synapse_qa.mdc +4 -3
  34. package/templates/ai_bridges/windsurfrules +1 -0
  35. package/tools/.infer_baseline.json +7 -1079
  36. package/tools/TOOLS_RUNBOOK.md +53 -13
  37. package/tools/__init__.py +1 -1
  38. package/tools/agent_canary.py +4 -4
  39. package/tools/analyze_project.py +2 -2
  40. package/tools/api_fuzzer.py +4 -4
  41. package/tools/auto_heal.py +4 -2
  42. package/tools/browser_helpers.js +2 -2
  43. package/tools/bump_version.py +30 -2
  44. package/tools/cache_resolver.py +6 -6
  45. package/tools/check_env.py +13 -7
  46. package/tools/cli.py +265 -197
  47. package/tools/count_tokens.py +7 -7
  48. package/tools/dashboard_generator.py +14 -14
  49. package/tools/db_sandbox.py +5 -5
  50. package/tools/debt_harvester.py +236 -0
  51. package/tools/distill_log.py +2 -2
  52. package/tools/flaky_detector.py +5 -5
  53. package/tools/generate_tc_from_story.py +2 -2
  54. package/tools/generate_test_reports.py +4 -4
  55. package/tools/git_pre_commit_guard.py +6 -6
  56. package/tools/infer_linter.py +12 -7
  57. package/tools/lint_ai_docs.py +2 -2
  58. package/tools/matrix_sharder.py +4 -4
  59. package/tools/mcp_excel_server.py +1 -1
  60. package/tools/mcp_server.py +3 -3
  61. package/tools/micro_mutator.py +6 -6
  62. package/tools/omni_transpiler.py +2 -2
  63. package/tools/output_formatter.py +37 -2
  64. package/tools/pinpoint_failure.py +4 -1
  65. package/tools/repo_map.py +2 -2
  66. package/tools/safety_firewall.py +2 -2
  67. package/tools/senior_code_review.py +341 -0
  68. package/tools/setup_project.py +9 -9
  69. package/tools/skillspector.py +2 -2
  70. package/tools/sync_agent_rules.py +14 -3
  71. package/tools/test_impact.py +4 -4
  72. package/tools/tms_sync_bridge.py +2 -2
  73. package/tools/update_sentinel.py +17 -17
  74. package/tools/verify_all.py +12 -12
  75. package/tools/visual_som_helper.py +8 -8
  76. package/tools/watch_mode.py +6 -7
  77. package/tools/wcag_audit.py +5 -1
  78. package/tools/welcome_page.py +11 -11
  79. package/benchmarks/qa_eval/README.md +0 -71
  80. package/benchmarks/qa_eval/build_dataset.py +0 -677
  81. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-06_api_contract_drift.json +0 -22
  82. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-07_api_contract_drift.json +0 -22
  83. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-08_api_contract_drift.json +0 -22
  84. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-09_api_contract_drift.json +0 -22
  85. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-10_api_contract_drift.json +0 -22
  86. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-21_fake_pass_tautology.json +0 -21
  87. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-22_fake_pass_tautology.json +0 -21
  88. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-23_fake_pass_tautology.json +0 -21
  89. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-24_fake_pass_tautology.json +0 -21
  90. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-25_fake_pass_tautology.json +0 -21
  91. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-01_locator_drift.json +0 -23
  92. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-02_locator_drift.json +0 -23
  93. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-03_locator_drift.json +0 -23
  94. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-04_locator_drift.json +0 -23
  95. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-05_locator_drift.json +0 -23
  96. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-16_stale_and_mutation.json +0 -22
  97. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-17_stale_and_mutation.json +0 -22
  98. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-18_stale_and_mutation.json +0 -22
  99. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-19_stale_and_mutation.json +0 -22
  100. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-20_stale_and_mutation.json +0 -23
  101. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-11_timing_and_race.json +0 -22
  102. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-12_timing_and_race.json +0 -22
  103. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-13_timing_and_race.json +0 -22
  104. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-14_timing_and_race.json +0 -22
  105. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-15_timing_and_race.json +0 -22
  106. package/benchmarks/qa_eval/eval_runner.py +0 -418
  107. package/examples/cypress-ecommerce-suite/README.md +0 -45
  108. package/examples/cypress-ecommerce-suite/cypress/e2e/checkout.cy.js +0 -17
  109. package/examples/cypress-ecommerce-suite/cypress/pages/BasePage.js +0 -29
  110. package/examples/cypress-ecommerce-suite/cypress/pages/CartPage.js +0 -51
  111. package/examples/cypress-ecommerce-suite/cypress.config.js +0 -13
  112. package/examples/cypress-ecommerce-suite/package.json +0 -13
  113. package/examples/katalon-suite/Keywords/pages/BasePage.groovy +0 -19
  114. package/examples/katalon-suite/Keywords/pages/DashboardPage.groovy +0 -29
  115. package/examples/katalon-suite/Keywords/pages/LoginPage.groovy +0 -45
  116. package/examples/katalon-suite/Profiles/default.glbl +0 -12
  117. package/examples/katalon-suite/README.md +0 -18
  118. package/examples/katalon-suite/Scripts/Auth/TC_LoginSuccess/Script1234567890.groovy +0 -12
  119. package/examples/katalon-suite/Scripts/Dashboard/TC_ViewSummary/Script1234567891.groovy +0 -15
  120. package/examples/katalon-suite/katalon_suite.prj +0 -21
  121. package/examples/playwright-crm-suite/README.md +0 -40
  122. package/examples/playwright-crm-suite/package.json +0 -14
  123. package/examples/playwright-crm-suite/pages/BasePage.ts +0 -37
  124. package/examples/playwright-crm-suite/pages/CustomerPage.ts +0 -57
  125. package/examples/playwright-crm-suite/pages/LoginPage.ts +0 -32
  126. package/examples/playwright-crm-suite/playwright.config.ts +0 -27
  127. package/examples/playwright-crm-suite/tests/auth.spec.ts +0 -22
  128. package/examples/playwright-crm-suite/tests/customers.spec.ts +0 -33
  129. package/examples/plugins/sample-custom-plugin/README.md +0 -14
  130. package/examples/plugins/sample-custom-plugin/plugin.json +0 -16
  131. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/SKILL.md +0 -29
  132. package/examples/plugins/sample-custom-plugin/skills/custom-security-headers-audit/examples/audit_fixture.json +0 -8
  133. package/examples/plugins/sample-custom-plugin/tools/custom_security_headers.py +0 -125
  134. package/examples/practices/README.md +0 -22
  135. package/examples/practices/requirements/crm/requirements_contracts.md +0 -292
  136. package/examples/practices/requirements/crm/requirements_customers.md +0 -462
  137. package/examples/practices/requirements/crm/requirements_login.md +0 -202
  138. package/examples/practices/requirements/crm/requirements_projects.md +0 -396
  139. package/examples/practices/requirements/crm/requirements_tasks.md +0 -343
  140. package/examples/practices/requirements/ecommerce/requirements_category_brand.txt +0 -402
  141. package/examples/practices/requirements/jira/KAN-5/KAN-1/2026-04-03_04-28-27.png +0 -0
  142. package/examples/practices/requirements/jira/KAN-5/KAN-1/KAN-1_requirement.md +0 -52
  143. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-19.png +0 -0
  144. package/examples/practices/requirements/jira/KAN-5/KAN-4/2026-04-03_04-28-57.png +0 -0
  145. package/examples/practices/requirements/jira/KAN-5/KAN-4/KAN-4_requirement.md +0 -119
  146. package/examples/practices/requirements/jira/KAN-5/KAN-5_overview.md +0 -9
  147. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-08.png +0 -0
  148. package/examples/practices/requirements/jira/KAN-5/KAN-6/2026-04-03_05-58-23.png +0 -0
  149. package/examples/practices/requirements/jira/KAN-5/KAN-6/KAN-6_requirement.md +0 -32
  150. package/examples/practices/testcases/api/book_management_api_test_cases.md +0 -144
  151. package/examples/practices/testcases/api/user_management_api_test_cases.md +0 -139
  152. package/examples/practices/testcases/crm/test_cases_crm_login.md +0 -148
  153. package/examples/practices/testcases/crm/test_cases_customers.md +0 -156
  154. package/examples/pytest-api-suite/README.md +0 -45
  155. package/examples/pytest-api-suite/conftest.py +0 -31
  156. package/examples/pytest-api-suite/pages/user_api_client.py +0 -36
  157. package/examples/pytest-api-suite/requirements.txt +0 -2
  158. package/examples/pytest-api-suite/tests/test_user_api.py +0 -44
  159. package/examples/selenium-suite/README.md +0 -18
  160. package/examples/selenium-suite/pages/base_page.py +0 -27
  161. package/examples/selenium-suite/pages/login_page.py +0 -29
  162. package/examples/selenium-suite/pages/order_page.py +0 -25
  163. package/examples/selenium-suite/pytest.ini +0 -6
  164. package/examples/selenium-suite/requirements.txt +0 -2
  165. package/examples/selenium-suite/tests/test_login.py +0 -10
  166. package/examples/selenium-suite/tests/test_order.py +0 -10
package/tools/cli.py CHANGED
@@ -41,7 +41,7 @@ RESET = "\033[0m"
41
41
  def cmd_version(args):
42
42
  """Displays the current hub version, skill catalog count, and license information."""
43
43
  manifest_path = os.path.join(REPO_ROOT, "skills_manifest.json")
44
- version = "2.4.3"
44
+ version = "2.5.0"
45
45
  if os.path.exists(manifest_path):
46
46
  try:
47
47
  import json
@@ -49,16 +49,16 @@ def cmd_version(args):
49
49
  data = json.load(f)
50
50
  version = data.get("version", version)
51
51
  except (OSError, json.JSONDecodeError):
52
- pass
52
+ data = {}
53
53
  print(f"Agent-QA Hub CLI v{version}")
54
- manifest_skills = 38
54
+ manifest_skills = 42
55
55
  if os.path.exists(manifest_path):
56
56
  try:
57
57
  import json
58
58
  with open(manifest_path, "r", encoding="utf-8") as f:
59
- manifest_skills = json.load(f).get("totalSkills", 38)
59
+ manifest_skills = json.load(f).get("totalSkills", 42)
60
60
  except (OSError, json.JSONDecodeError):
61
- pass
61
+ manifest_skills = 42
62
62
  print(f"Catalog: {manifest_skills} Standardized Skills | 6 Subagent Swarm Profiles")
63
63
  print("Created by: Thế Vị (@TeeVee998) <https://github.com/TeeVee998/Synapse-Hub>")
64
64
  print("License : MIT (Attribution Required)")
@@ -144,8 +144,8 @@ def cmd_clean(args):
144
144
  try:
145
145
  os.remove(os.path.join(root, f))
146
146
  removed_count += 1
147
- except OSError:
148
- pass
147
+ except OSError as err:
148
+ failed_files = getattr(args, "verbose", False) and print(f"Notice: Could not remove {f}: {err}")
149
149
  print(f"✅ Cleanup finished: {removed_count} build artifacts and caches removed.")
150
150
 
151
151
 
@@ -514,16 +514,42 @@ def cmd_mcp_excel(args):
514
514
  sys.exit(mcp_excel_main())
515
515
 
516
516
 
517
+ def cmd_debt(args):
518
+ """Harvests shortcut: and deliberate debt comments into a tracked technical debt ledger."""
519
+ from debt_harvester import main as debt_main
520
+ sys.argv = _forward_subcommand_args(args)
521
+ sys.exit(debt_main())
522
+
523
+
524
+ def cmd_review(args):
525
+ """Senior developer diff & code review checking bugs, security, scale, missing tests, and bloat."""
526
+ from senior_code_review import main as review_main
527
+ sys.argv = _forward_subcommand_args(args)
528
+ sys.exit(review_main())
529
+
530
+
531
+ def cmd_release(args):
532
+ """1-Click atomic release: bumps version across all files, runs 9 Quality Gates, tags & pushes to trigger NPM Trusted Publishing."""
533
+ from bump_version import main as bump_main
534
+ forwarded = _forward_subcommand_args(args)
535
+ if "--no-push" not in forwarded and "--push" not in forwarded:
536
+ forwarded.append("--push")
537
+ if "--commit" not in forwarded and "--no-commit" not in forwarded:
538
+ forwarded.append("--commit")
539
+ sys.argv = forwarded
540
+ sys.exit(bump_main())
541
+
542
+
517
543
  def _hub_version():
518
544
  manifest_path = os.path.join(REPO_ROOT, "skills_manifest.json")
519
- version = "2.4.3"
545
+ version = "2.5.0"
520
546
  if os.path.exists(manifest_path):
521
547
  try:
522
548
  import json
523
549
  with open(manifest_path, "r", encoding="utf-8") as f:
524
550
  version = json.load(f).get("version", version)
525
551
  except (OSError, json.JSONDecodeError):
526
- pass
552
+ version = "2.5.0"
527
553
  return version
528
554
 
529
555
 
@@ -551,30 +577,8 @@ class SynapseArgumentParser(argparse.ArgumentParser):
551
577
  super().error(message)
552
578
 
553
579
 
554
- def main():
555
- parser = SynapseArgumentParser(
556
- prog="agent-qa",
557
- description="Enterprise AI Agent Quality Engineering & Test Automation Hub CLI"
558
- )
559
- parser.add_argument(
560
- "--version",
561
- action="version",
562
- version=f"Agent-QA Hub CLI v{_hub_version()}"
563
- )
564
- parser.add_argument(
565
- "--offline", "--offline-deterministic",
566
- action="store_true",
567
- dest="offline",
568
- help="Force 100%% offline air-gapped deterministic mode (zero external network / LLM API calls)"
569
- )
570
- parser.add_argument(
571
- "-q", "--quiet",
572
- action="store_true",
573
- dest="quiet",
574
- help="Suppress informational banners and output only critical verdicts"
575
- )
576
- subparsers = parser.add_subparsers(dest="subcommand", help="Available subcommands")
577
-
580
+ def _register_core_and_setup_commands(subparsers):
581
+ """Registers core environment, setup, and informational subcommands."""
578
582
  # version
579
583
  p_ver = subparsers.add_parser("version", help="Show Hub version and catalog metadata")
580
584
  p_ver.set_defaults(func=cmd_version)
@@ -595,6 +599,55 @@ def main():
595
599
  p_uninstall.add_argument("target", nargs="?", default=None, help="Target repository path to revert")
596
600
  p_uninstall.set_defaults(func=cmd_uninstall)
597
601
 
602
+ # welcome
603
+ p_welcome = subparsers.add_parser("welcome", description="Interactive Visual Landing Page", help="Launch interactive visual landing page introducing Synapse Hub")
604
+ p_welcome.add_argument("target", nargs="?", default=None, help="Target repository directory (default: current directory)")
605
+ p_welcome.add_argument("--output", "-o", default=None, help="Output HTML file path (default: reports/WELCOME.html)")
606
+ p_welcome.add_argument("--lang", choices=["vi", "en"], default="vi", help="Default initial language (default: vi = Vietnamese)")
607
+ p_welcome.add_argument("--no-browser", action="store_true", help="Do not open the browser after generating the page")
608
+ p_welcome.add_argument("--open", action="store_true", help="Explicitly open the browser")
609
+ p_welcome.add_argument("--first-run", action="store_true", help="Only open if running for the first time (e.g. npm install or first pull)")
610
+ p_welcome.set_defaults(func=cmd_welcome)
611
+
612
+ # dashboard
613
+ p_dashboard = subparsers.add_parser("dashboard", help="Generate standalone one-page executive HTML dashboard (zero CDN deps)")
614
+ p_dashboard.add_argument("target", nargs="?", default=None, help="Target repository directory (default: current or Hub)")
615
+ p_dashboard.add_argument("--output", "-o", help="Output HTML file path (default: <target>/reports/PROJECT_DASHBOARD.html)")
616
+ p_dashboard.add_argument("--open", action="store_true", help="Automatically open generated dashboard in default browser")
617
+ p_dashboard.add_argument("--json", action="store_true", help="Print summary JSON to stdout")
618
+ p_dashboard.add_argument("--lang", choices=["vi", "en"], default="vi", help="Default display language (vi: Tiếng Việt, en: English, default: vi)")
619
+ p_dashboard.set_defaults(func=cmd_dashboard)
620
+
621
+ # clean
622
+ p_clean = subparsers.add_parser("clean", help="Clean build artifacts, __pycache__, and bytecode")
623
+ p_clean.set_defaults(func=cmd_clean)
624
+
625
+ # update
626
+ p_update = subparsers.add_parser("update", help="1-Click update Synapse-Hub to latest version from GitHub/NPM")
627
+ p_update.add_argument("--check", action="store_true", help="Check for available updates without applying")
628
+ p_update.set_defaults(func=cmd_update)
629
+
630
+ # check-version
631
+ p_ver_sync = subparsers.add_parser("check-version", help="Verify universal version synchronization across all files")
632
+ p_ver_sync.add_argument("--expected-version", "-e", help="Expected version string (e.g. from git tag)", default=None)
633
+ p_ver_sync.set_defaults(func=cmd_check_version)
634
+
635
+ # sync-rules
636
+ p_sync_rules = subparsers.add_parser("sync-rules", help="Synchronize AGENTS.md single source of truth across all AI IDE bridges")
637
+ p_sync_rules.add_argument("--check", action="store_true", help="Verify all AI bridges are in sync without writing")
638
+ p_sync_rules.set_defaults(func=cmd_sync_rules)
639
+
640
+
641
+ def _register_testing_and_execution_commands(subparsers):
642
+ """Registers automated testing, linting, healing, and mutation subcommands."""
643
+ # verify
644
+ p_verify = subparsers.add_parser("verify", help="Execute 9 Quality Gates DoD Verification")
645
+ p_verify.set_defaults(func=cmd_verify)
646
+
647
+ # lint
648
+ p_lint = subparsers.add_parser("lint", help="Run AST Fake-Pass & Zero-Assertion Sentinel")
649
+ p_lint.set_defaults(func=cmd_lint)
650
+
598
651
  # auto-heal
599
652
  p_auto_heal = subparsers.add_parser("auto-heal", help="Autonomous closed-loop test failure diagnosis and healing plan")
600
653
  p_auto_heal.set_defaults(func=cmd_auto_heal)
@@ -603,6 +656,10 @@ def main():
603
656
  p_heal_pr = subparsers.add_parser("heal-pr", help="Calculate self-healing confidence and generate Git PR draft")
604
657
  p_heal_pr.set_defaults(func=cmd_heal_pr)
605
658
 
659
+ # heal (memory cache)
660
+ p_heal = subparsers.add_parser("heal", help="Query, learn, or record-failed into semantic memory cache")
661
+ p_heal.set_defaults(func=cmd_heal)
662
+
606
663
  # mutate
607
664
  p_mut = subparsers.add_parser("mutate", help="Inject syntactic micro-mutants to verify test assertion strength")
608
665
  p_mut.set_defaults(func=cmd_mutate)
@@ -611,6 +668,54 @@ def main():
611
668
  p_shard = subparsers.add_parser("shard", help="Balance parallel CI/CD test execution using duration-balanced bin-packing")
612
669
  p_shard.set_defaults(func=cmd_shard)
613
670
 
671
+ # flaky
672
+ p_flaky = subparsers.add_parser("flaky", help="Detect flaky tests and manage quarantine lifecycle")
673
+ p_flaky.set_defaults(func=cmd_flaky)
674
+
675
+ # canary
676
+ p_canary = subparsers.add_parser("canary", help="Run autonomous canary resilience benchmark")
677
+ p_canary.set_defaults(func=cmd_canary)
678
+
679
+ # watch
680
+ p_watch = subparsers.add_parser("watch", help="Real-Time incremental watch mode & test engineering HUD (< 100ms feedback)")
681
+ p_watch.add_argument("target", nargs="?", default=".", help="Directory to monitor (default: current directory)")
682
+ p_watch.add_argument("--debounce", type=float, default=0.8, help="Debounce interval in seconds (default: 0.8)")
683
+ p_watch.add_argument("--inactivity-timeout", type=float, default=0.0, help="Inactivity timeout in seconds to trigger stuck warning (default: 0 = disabled)")
684
+ p_watch.add_argument("--once", action="store_true", help="Run incremental scan once on all files and exit")
685
+ p_watch.set_defaults(func=cmd_watch)
686
+
687
+ # pinpoint-failure
688
+ p_pinpoint = subparsers.add_parser("pinpoint-failure", help="Parse JUnit XML and locate exact failing line in 0.1s")
689
+ p_pinpoint.add_argument("report_file", nargs="?", default="", help="Path to JUnit XML test report")
690
+ p_pinpoint.set_defaults(func=cmd_pinpoint_failure)
691
+
692
+ # ci-hook
693
+ p_ci = subparsers.add_parser("ci-hook", help="CI/CD Silent Self-Healing Pipeline Hook & Automated PR Generator")
694
+ p_ci.set_defaults(func=cmd_ci_hook)
695
+
696
+
697
+ def _register_audit_and_inspection_commands(subparsers):
698
+ """Registers security, architecture, and code quality inspection subcommands."""
699
+ # analyze
700
+ p_analyze = subparsers.add_parser("analyze", help="Execute Comprehensive Project Health & AST Analysis")
701
+ p_analyze.set_defaults(func=cmd_analyze)
702
+
703
+ # debt
704
+ p_debt = subparsers.add_parser("debt", aliases=["harvest-debt"], help="Harvest shortcut: comments into a tracked technical debt ledger")
705
+ p_debt.add_argument("target", nargs="?", default=".", help="Directory to scan (default: current directory)")
706
+ p_debt.add_argument("--keyword", "-k", default=None, help="Custom marker keyword (default: shortcut or ponytail)")
707
+ p_debt.add_argument("--output", "-o", default=None, help="Save report to Markdown file")
708
+ p_debt.add_argument("--json", action="store_true", help="Output results in JSON format")
709
+ p_debt.set_defaults(func=cmd_debt)
710
+
711
+ # review
712
+ p_review = subparsers.add_parser("review", aliases=["code-review"], help="Senior developer quality & lean diff review (bugs, security, scale, tests, bloat)")
713
+ p_review.add_argument("target_dir", nargs="?", default=".", help="Repository directory (default: current directory)")
714
+ p_review.add_argument("--staged", action="store_true", help="Review staged git changes")
715
+ p_review.add_argument("--branch", default=None, help="Review changes against a git branch or commit ref")
716
+ p_review.add_argument("--json", action="store_true", help="Output results in JSON format")
717
+ p_review.set_defaults(func=cmd_review)
718
+
614
719
  # safety-check
615
720
  p_safety = subparsers.add_parser("safety-check", help="Action Safety Firewall & Blast Radius Containment")
616
721
  p_safety.set_defaults(func=cmd_safety_check)
@@ -619,50 +724,59 @@ def main():
619
724
  p_drift = subparsers.add_parser("contract-drift", help="Detect breaking API changes across OpenAPI / Swagger specs")
620
725
  p_drift.set_defaults(func=cmd_contract_drift)
621
726
 
622
- # mcp-serve
623
- p_mcp = subparsers.add_parser("mcp-serve", help="Start the JSON-RPC 2.0 stdio Model Context Protocol (MCP) server")
624
- p_mcp.set_defaults(func=cmd_mcp_serve)
727
+ # skillspector
728
+ p_skillspector = subparsers.add_parser("skillspector", help="AI Agent Skill & MCP Security Sentinel (71 vectors, NVIDIA SkillSpector spec)")
729
+ p_skillspector.add_argument("path", nargs="?", default=".", help="Skill directory or file to scan (default: current directory)")
730
+ p_skillspector.add_argument("--format", choices=["terminal", "json", "markdown", "sarif"], default="terminal", help="Output format")
731
+ p_skillspector.add_argument("--output", "-o", help="Write report to output file")
732
+ p_skillspector.add_argument("--strict", action="store_true", help="Fail with non-zero exit code on HIGH/CRITICAL finding")
733
+ p_skillspector.set_defaults(func=cmd_skillspector)
625
734
 
626
- # analyze
627
- p_analyze = subparsers.add_parser("analyze", help="Execute Comprehensive Project Health & AST Analysis")
628
- p_analyze.set_defaults(func=cmd_analyze)
735
+ # verify-author
736
+ p_author = subparsers.add_parser("verify-author", help="Verify author attribution, provenance, and anti-tamper integrity")
737
+ p_author.set_defaults(func=cmd_verify_author)
629
738
 
630
- # verify
631
- p_verify = subparsers.add_parser("verify", help="Execute 9 Quality Gates DoD Verification")
632
- p_verify.set_defaults(func=cmd_verify)
739
+ # wcag-audit
740
+ p_wcag = subparsers.add_parser("wcag-audit", help="Audit WCAG 2.2 accessibility conformance and contrast ratios")
741
+ p_wcag.add_argument("target", nargs="?", default=".", help="Target HTML file or directory to audit")
742
+ p_wcag.set_defaults(func=cmd_wcag_audit)
633
743
 
634
- # lint
635
- p_lint = subparsers.add_parser("lint", help="Run AST Fake-Pass & Zero-Assertion Sentinel")
636
- p_lint.set_defaults(func=cmd_lint)
744
+ # impact
745
+ p_impact = subparsers.add_parser("impact", help="Analyze code change impact using AST Knowledge Graph")
746
+ p_impact.set_defaults(func=cmd_impact)
637
747
 
638
- # heal
639
- p_heal = subparsers.add_parser("heal", help="Query, learn, or record-failed into semantic memory cache")
640
- p_heal.set_defaults(func=cmd_heal)
748
+ # review-spec
749
+ p_review_spec = subparsers.add_parser("review-spec", help="Zero-context stress-test for specifications and user stories (Elephant-Goldfish Model)")
750
+ p_review_spec.add_argument("spec_file", nargs="?", default="", help="Path to specification file (Markdown or Gherkin .feature, use '-' for stdin)")
751
+ p_review_spec.add_argument("--stdin", action="store_true", help="Read specification from standard input (stdin)")
752
+ p_review_spec.add_argument("--json", action="store_true", help="Output machine-readable JSON format")
753
+ p_review_spec.add_argument("--min-score", type=int, default=80, help="Minimum readiness score threshold (default: 80)")
754
+ p_review_spec.set_defaults(func=cmd_review_spec)
755
+
756
+ # drift-check
757
+ p_spec_drift = subparsers.add_parser("drift-check", help="Spec-to-Code Drift Sentinel checking Deficit & Scope Drift")
758
+ p_spec_drift.add_argument("--spec", required=True, help="Path to specification file (Markdown or Gherkin .feature)")
759
+ p_spec_drift.add_argument("--code", required=True, help="Path to test script or directory of test scripts")
760
+ p_spec_drift.add_argument("--markdown", "-m", help="Path to export Markdown drift report (e.g. SPEC_DRIFT_REPORT.md)")
761
+ p_spec_drift.add_argument("--json", action="store_true", help="Output machine-readable JSON format")
762
+ p_spec_drift.set_defaults(func=cmd_drift_check)
763
+
764
+ # trace-data-flow
765
+ p_trace = subparsers.add_parser("trace-data-flow", help="Trace test data lifecycles to detect DB leaks and missing teardowns")
766
+ p_trace.add_argument("target", nargs="?", default=".", help="Target test directory to inspect")
767
+ p_trace.set_defaults(func=cmd_trace_data_flow)
641
768
 
769
+
770
+ def _register_platform_and_tools_commands(subparsers):
771
+ """Registers protocol generators, converters, MCP servers, and utility subcommands."""
642
772
  # distill
643
773
  p_distill = subparsers.add_parser("distill", help="Distill and filter verbose CLI logs by 95 percent")
644
774
  p_distill.set_defaults(func=cmd_distill)
645
775
 
646
- # impact
647
- p_impact = subparsers.add_parser("impact", help="Analyze code change impact using AST Knowledge Graph")
648
- p_impact.set_defaults(func=cmd_impact)
649
-
650
776
  # gherkin
651
777
  p_gherkin = subparsers.add_parser("gherkin", help="Compile Gherkin .feature files into test matrix, Universal IR and coverage-gap report (0-token)")
652
778
  p_gherkin.set_defaults(func=cmd_gherkin)
653
779
 
654
- # canary
655
- p_canary = subparsers.add_parser("canary", help="Run autonomous canary resilience benchmark")
656
- p_canary.set_defaults(func=cmd_canary)
657
-
658
- # clean
659
- p_clean = subparsers.add_parser("clean", help="Clean build artifacts, __pycache__, and bytecode")
660
- p_clean.set_defaults(func=cmd_clean)
661
-
662
- # flaky
663
- p_flaky = subparsers.add_parser("flaky", help="Detect flaky tests and manage quarantine lifecycle")
664
- p_flaky.set_defaults(func=cmd_flaky)
665
-
666
780
  # transpile
667
781
  p_trans = subparsers.add_parser("transpile", help="Transpile test files across languages and frameworks (0-token)")
668
782
  p_trans.add_argument("source", help="Source file path")
@@ -688,10 +802,6 @@ def main():
688
802
  p_mask = subparsers.add_parser("visual-mask", help="Smart Visual Masking & Anti-Flake Animation Blocker")
689
803
  p_mask.set_defaults(func=cmd_visual_mask)
690
804
 
691
- # ci-hook
692
- p_ci = subparsers.add_parser("ci-hook", help="CI/CD Silent Self-Healing Pipeline Hook & Automated PR Generator")
693
- p_ci.set_defaults(func=cmd_ci_hook)
694
-
695
805
  # migrate
696
806
  p_migrate = subparsers.add_parser("migrate", help="Autonomous suite migration from legacy (Katalon/Cypress) to modern Playwright")
697
807
  p_migrate.add_argument("--src", required=True, help="Source legacy test suite file or directory")
@@ -710,7 +820,7 @@ def main():
710
820
  p_fuzz = subparsers.add_parser("fuzz-api", help="Autonomous API Fuzzing & Chaos Breaker (bắn mutation payloads, bắt 500, DB leak, SLA breach)")
711
821
  p_fuzz.set_defaults(func=cmd_fuzz_api)
712
822
 
713
- # som (Visual Grounding for Canvas / GIS)
823
+ # som
714
824
  p_som = subparsers.add_parser("som", help="Multimodal Vision Grounding & Set-of-Marks (SoM) for Canvas/GIS without DOM")
715
825
  p_som.set_defaults(func=cmd_som)
716
826
 
@@ -741,24 +851,7 @@ def main():
741
851
  p_newman = subparsers.add_parser("analyze-newman", help="Analyze Postman / Newman test results, triage failed assertions, and enforce CI/CD Quality Gate")
742
852
  p_newman.set_defaults(func=cmd_analyze_newman)
743
853
 
744
- # update
745
- p_update = subparsers.add_parser("update", help="1-Click update Synapse-Hub to latest version from GitHub/NPM")
746
- p_update.add_argument("--check", action="store_true", help="Check for available updates without applying")
747
- p_update.set_defaults(func=cmd_update)
748
-
749
- # skillspector (AI Agent Skill & MCP Security Scanner)
750
- p_skillspector = subparsers.add_parser("skillspector", help="AI Agent Skill & MCP Security Sentinel (71 vectors, NVIDIA SkillSpector spec)")
751
- p_skillspector.add_argument("path", nargs="?", default=".", help="Skill directory or file to scan (default: current directory)")
752
- p_skillspector.add_argument("--format", choices=["terminal", "json", "markdown", "sarif"], default="terminal", help="Output format")
753
- p_skillspector.add_argument("--output", "-o", help="Write report to output file")
754
- p_skillspector.add_argument("--strict", action="store_true", help="Fail with non-zero exit code on HIGH/CRITICAL finding")
755
- p_skillspector.set_defaults(func=cmd_skillspector)
756
-
757
- # verify-author (Author Provenance & Anti-Tamper Integrity Guard)
758
- p_author = subparsers.add_parser("verify-author", help="Verify author attribution, provenance, and anti-tamper integrity")
759
- p_author.set_defaults(func=cmd_verify_author)
760
-
761
- # tokens (Cross-Platform Token & Cost Auditor)
854
+ # tokens
762
855
  p_tokens = subparsers.add_parser("tokens", help="Audit token usage and estimated API cost across Antigravity, Cursor, and Claude Code")
763
856
  p_tokens.add_argument("--platform", "-p", choices=["auto", "antigravity", "cursor", "claude", "all"], default="auto", help="AI platform to audit (default: auto)")
764
857
  p_tokens.add_argument("--session", type=str, help="Specific session ID or index to audit")
@@ -775,84 +868,21 @@ def main():
775
868
  p_tokens.add_argument("--file", type=str, help="Direct path to a transcript.jsonl file")
776
869
  p_tokens.set_defaults(func=cmd_tokens)
777
870
 
778
- # dashboard (Standalone One-Page HTML Executive Dashboard)
779
- p_dashboard = subparsers.add_parser("dashboard", help="Generate standalone one-page executive HTML dashboard (zero CDN deps)")
780
- p_dashboard.add_argument("target", nargs="?", default=None, help="Target repository directory (default: current or Hub)")
781
- p_dashboard.add_argument("--output", "-o", help="Output HTML file path (default: <target>/reports/PROJECT_DASHBOARD.html)")
782
- p_dashboard.add_argument("--open", action="store_true", help="Automatically open generated dashboard in default browser")
783
- p_dashboard.add_argument("--json", action="store_true", help="Print summary JSON to stdout")
784
- p_dashboard.add_argument("--lang", choices=["vi", "en"], default="vi", help="Default display language (vi: Tiếng Việt, en: English, default: vi)")
785
- p_dashboard.set_defaults(func=cmd_dashboard)
786
-
787
- # watch (Real-Time Incremental Watch Mode Sentinel)
788
- p_watch = subparsers.add_parser("watch", help="Real-Time incremental watch mode & test engineering HUD (< 100ms feedback)")
789
- p_watch.add_argument("target", nargs="?", default=".", help="Directory to monitor (default: current directory)")
790
- p_watch.add_argument("--debounce", type=float, default=0.8, help="Debounce interval in seconds (default: 0.8)")
791
- p_watch.add_argument("--inactivity-timeout", type=float, default=0.0, help="Inactivity timeout in seconds to trigger stuck warning (default: 0 = disabled)")
792
- p_watch.add_argument("--once", action="store_true", help="Run incremental scan once on all files and exit")
793
- p_watch.set_defaults(func=cmd_watch)
794
-
795
- # welcome (Interactive Visual Landing Page)
796
- p_welcome = subparsers.add_parser("welcome", description="Interactive Visual Landing Page", help="Launch interactive visual landing page introducing Synapse Hub")
797
- p_welcome.add_argument("target", nargs="?", default=None, help="Target repository directory (default: current directory)")
798
- p_welcome.add_argument("--output", "-o", default=None, help="Output HTML file path (default: reports/WELCOME.html)")
799
- p_welcome.add_argument("--lang", choices=["vi", "en"], default="vi", help="Default initial language (default: vi = Vietnamese)")
800
- p_welcome.add_argument("--no-browser", action="store_true", help="Do not open the browser after generating the page")
801
- p_welcome.add_argument("--open", action="store_true", help="Explicitly open the browser")
802
- p_welcome.add_argument("--first-run", action="store_true", help="Only open if running for the first time (e.g. npm install or first pull)")
803
- p_welcome.set_defaults(func=cmd_welcome)
804
-
805
- # wcag-audit (WCAG 2.2 Accessibility Sentinel)
806
- p_wcag = subparsers.add_parser("wcag-audit", help="Audit WCAG 2.2 accessibility conformance and contrast ratios")
807
- p_wcag.add_argument("target", nargs="?", default=".", help="Target HTML file or directory to audit")
808
- p_wcag.set_defaults(func=cmd_wcag_audit)
809
-
810
- # lookup-tc (Deterministic Test Case Identifier Index)
871
+ # lookup-tc
811
872
  p_lookup_tc = subparsers.add_parser("lookup-tc", help="Search test cases by ID, tag, priority, or flow")
812
873
  p_lookup_tc.add_argument("query", nargs="?", default="", help="Query keyword or TC ID")
813
874
  p_lookup_tc.set_defaults(func=cmd_lookup_tc)
814
875
 
815
- # lookup-xpath (AOM & DOM Selector Lookup Cache)
876
+ # lookup-xpath
816
877
  p_lookup_xpath = subparsers.add_parser("lookup-xpath", help="Query cached resilient XPath & AOM locators")
817
878
  p_lookup_xpath.add_argument("query", nargs="?", default="", help="Element text, test-id, or locator label")
818
879
  p_lookup_xpath.set_defaults(func=cmd_lookup_xpath)
819
880
 
820
- # trace-data-flow (Idempotent Data Flow & Taint Analysis)
821
- p_trace = subparsers.add_parser("trace-data-flow", help="Trace test data lifecycles to detect DB leaks and missing teardowns")
822
- p_trace.add_argument("target", nargs="?", default=".", help="Target test directory to inspect")
823
- p_trace.set_defaults(func=cmd_trace_data_flow)
824
-
825
- # generate-tc (User Story & Acceptance Criteria Compiler)
881
+ # generate-tc
826
882
  p_gen_tc = subparsers.add_parser("generate-tc", help="Compile natural language user stories into Clean POM test cases")
827
883
  p_gen_tc.add_argument("story_file", nargs="?", default="", help="Path to markdown/text user story specification")
828
884
  p_gen_tc.set_defaults(func=cmd_generate_tc)
829
885
 
830
- # pinpoint-failure (Instant JUnit XML Root Cause Autopsy)
831
- p_pinpoint = subparsers.add_parser("pinpoint-failure", help="Parse JUnit XML and locate exact failing line in 0.1s")
832
- p_pinpoint.add_argument("report_file", nargs="?", default="", help="Path to JUnit XML test report")
833
- p_pinpoint.set_defaults(func=cmd_pinpoint_failure)
834
-
835
- # sync-rules (Single-Source Agent Rules Synchronizer)
836
- p_sync_rules = subparsers.add_parser("sync-rules", help="Synchronize AGENTS.md single source of truth across all AI IDE bridges")
837
- p_sync_rules.add_argument("--check", action="store_true", help="Verify all AI bridges are in sync without writing")
838
- p_sync_rules.set_defaults(func=cmd_sync_rules)
839
-
840
- # review-spec (Zero-Context Test Spec Auditor - Elephant-Goldfish Model)
841
- p_review = subparsers.add_parser("review-spec", help="Zero-context stress-test for specifications and user stories (Elephant-Goldfish Model)")
842
- p_review.add_argument("spec_file", nargs="?", default="", help="Path to specification file (Markdown or Gherkin .feature, use '-' for stdin)")
843
- p_review.add_argument("--stdin", action="store_true", help="Read specification from standard input (stdin)")
844
- p_review.add_argument("--json", action="store_true", help="Output machine-readable JSON format")
845
- p_review.add_argument("--min-score", type=int, default=80, help="Minimum readiness score threshold (default: 80)")
846
- p_review.set_defaults(func=cmd_review_spec)
847
-
848
- # drift-check (Spec-to-Code Drift Sentinel)
849
- p_drift = subparsers.add_parser("drift-check", help="Spec-to-Code Drift Sentinel checking Deficit & Scope Drift")
850
- p_drift.add_argument("--spec", required=True, help="Path to specification file (Markdown or Gherkin .feature)")
851
- p_drift.add_argument("--code", required=True, help="Path to test script or directory of test scripts")
852
- p_drift.add_argument("--markdown", "-m", help="Path to export Markdown drift report (e.g. SPEC_DRIFT_REPORT.md)")
853
- p_drift.add_argument("--json", action="store_true", help="Output machine-readable JSON format")
854
- p_drift.set_defaults(func=cmd_drift_check)
855
-
856
886
  # api-matrix
857
887
  p_api_mat = subparsers.add_parser("api-matrix", help="Generate Positive, Boundary, and Negative test matrix from OpenAPI/Swagger")
858
888
  p_api_mat.add_argument("--spec", "-s", help="Path to OpenAPI / Swagger JSON/YAML file")
@@ -872,60 +902,98 @@ def main():
872
902
  p_groovy.add_argument("--dir", "-d", help="Explicit directory to scan")
873
903
  p_groovy.set_defaults(func=cmd_validate_groovy)
874
904
 
875
- # check-version
876
- p_ver_sync = subparsers.add_parser("check-version", help="Verify universal version synchronization across all files")
877
- p_ver_sync.add_argument("--expected-version", "-e", help="Expected version string (e.g. from git tag)", default=None)
878
- p_ver_sync.set_defaults(func=cmd_check_version)
905
+ # mcp-serve
906
+ p_mcp = subparsers.add_parser("mcp-serve", help="Start the JSON-RPC 2.0 stdio Model Context Protocol (MCP) server")
907
+ p_mcp.set_defaults(func=cmd_mcp_serve)
879
908
 
880
909
  # mcp-excel
881
910
  p_mcp_excel = subparsers.add_parser("mcp-excel", help="Start the JSON-RPC 2.0 stdio MCP Excel server")
882
911
  p_mcp_excel.set_defaults(func=cmd_mcp_excel)
883
912
 
913
+ # release
914
+ p_release = subparsers.add_parser("release", help="1-Click atomic release: bump version across all targets, verify DoD gates, git tag & push for NPM Trusted Publishing")
915
+ p_release.add_argument("action", nargs="?", default="patch", help="patch | minor | major | <explicit_version> (default: patch)")
916
+ p_release.add_argument("--push", action="store_true", default=True, help="Auto-push commit and tag to origin to trigger CI release (default: true)")
917
+ p_release.add_argument("--no-push", dest="push", action="store_false", help="Do not push to remote")
918
+ p_release.add_argument("--no-test", action="store_true", help="Skip running tests before release")
919
+ p_release.set_defaults(func=cmd_release)
920
+
921
+
922
+ def _handle_interactive_wizard(parser, args):
923
+ """Offers a friendly quick-start menu if running in an interactive terminal."""
924
+ is_interactive = hasattr(sys.stdin, "isatty") and sys.stdin.isatty() and not os.environ.get("CI") and not os.environ.get("SYNAPSE_NON_INTERACTIVE")
925
+ if is_interactive:
926
+ print(f"\n{BOLD}{CYAN}======================================================================{RESET}")
927
+ print(f"{BOLD}{CYAN} 🧠 SYNAPSE HUB — INTERACTIVE TERMINAL WIZARD {RESET}")
928
+ print(f"{BOLD}{CYAN}======================================================================{RESET}")
929
+ print("Chào bạn! Hãy chọn nhanh một tác vụ để bắt đầu (hoặc nhấn Enter để xem Trợ Giúp):")
930
+ print(f" {BOLD}1.{RESET} 🩺 {BOLD}Doctor{RESET} - Kiểm tra chẩn đoán môi trường (Node, Python, Chrome, Git)")
931
+ print(f" {BOLD}2.{RESET} 🚀 {BOLD}Setup{RESET} - Thiết lập bảo vệ 1-click cho dự án kiểm thử mục tiêu")
932
+ print(f" {BOLD}3.{RESET} 🔍 {BOLD}Lint{RESET} - Quét phát hiện test pass ảo, 0 assert, sleep cứng")
933
+ print(f" {BOLD}4.{RESET} 🛡️ {BOLD}Verify{RESET} - Chạy kiểm tra 9 Cổng Chất Lượng DoD")
934
+ print(f" {BOLD}5.{RESET} 🌐 {BOLD}Welcome{RESET} - Mở trang Landing Page trực quan")
935
+ print(f" {BOLD}6.{RESET} ❓ {BOLD}Help{RESET} - Xem danh sách đầy đủ tất cả các lệnh CLI")
936
+ print(f"{BOLD}{CYAN}======================================================================{RESET}")
937
+ try:
938
+ choice = input(f"Nhập lựa chọn {BOLD}[1-6]{RESET} (mặc định: 6): ").strip()
939
+ except (EOFError, KeyboardInterrupt):
940
+ print()
941
+ sys.exit(0)
942
+
943
+ dispatch_map = {
944
+ "1": ("doctor", cmd_doctor),
945
+ "2": ("setup", cmd_setup),
946
+ "3": ("lint", cmd_lint),
947
+ "4": ("verify", cmd_verify),
948
+ "5": ("welcome", cmd_welcome),
949
+ }
950
+ if choice in dispatch_map:
951
+ subcmd, handler = dispatch_map[choice]
952
+ args.subcommand = subcmd
953
+ return handler(args)
954
+
955
+ parser.print_help()
956
+ print("\n💡 Tip: Run 'npx synapse-hub welcome' (or 'npm start') to launch the visual landing page.")
957
+ sys.exit(0)
958
+
959
+
960
+ def main():
961
+ parser = SynapseArgumentParser(
962
+ prog="agent-qa",
963
+ description="Enterprise AI Agent Quality Engineering & Test Automation Hub CLI"
964
+ )
965
+ parser.add_argument(
966
+ "--version",
967
+ action="version",
968
+ version=f"Agent-QA Hub CLI v{_hub_version()}"
969
+ )
970
+ parser.add_argument(
971
+ "--offline", "--offline-deterministic",
972
+ action="store_true",
973
+ dest="offline",
974
+ help="Force 100%% offline air-gapped deterministic mode (zero external network / LLM API calls)"
975
+ )
976
+ parser.add_argument(
977
+ "-q", "--quiet",
978
+ action="store_true",
979
+ dest="quiet",
980
+ help="Suppress informational banners and output only critical verdicts"
981
+ )
982
+ subparsers = parser.add_subparsers(dest="subcommand", help="Available subcommands")
983
+
984
+ # Modular command registration (Refactored Command Dispatcher Pattern)
985
+ _register_core_and_setup_commands(subparsers)
986
+ _register_testing_and_execution_commands(subparsers)
987
+ _register_audit_and_inspection_commands(subparsers)
988
+ _register_platform_and_tools_commands(subparsers)
989
+
884
990
  args, unknown = parser.parse_known_args()
885
991
  if getattr(args, "offline", False):
886
992
  os.environ["AGENT_QA_OFFLINE"] = "1"
887
993
  print("🔒 [OFFLINE MODE] Air-Gapped Deterministic Mode Active. 100% Local AST & Heuristics (Zero External API calls).")
888
994
 
889
995
  if not args.subcommand:
890
- # If running in an interactive terminal, offer a friendly quick-start menu
891
- is_interactive = hasattr(sys.stdin, "isatty") and sys.stdin.isatty() and not os.environ.get("CI") and not os.environ.get("SYNAPSE_NON_INTERACTIVE")
892
- if is_interactive:
893
- print(f"\n{BOLD}{CYAN}======================================================================{RESET}")
894
- print(f"{BOLD}{CYAN} 🧠 SYNAPSE HUB — INTERACTIVE TERMINAL WIZARD {RESET}")
895
- print(f"{BOLD}{CYAN}======================================================================{RESET}")
896
- print("Chào bạn! Hãy chọn nhanh một tác vụ để bắt đầu (hoặc nhấn Enter để xem Trợ Giúp):")
897
- print(f" {BOLD}1.{RESET} 🩺 {BOLD}Doctor{RESET} - Kiểm tra chẩn đoán môi trường (Node, Python, Chrome, Git)")
898
- print(f" {BOLD}2.{RESET} 🚀 {BOLD}Setup{RESET} - Thiết lập bảo vệ 1-click cho dự án kiểm thử mục tiêu")
899
- print(f" {BOLD}3.{RESET} 🔍 {BOLD}Lint{RESET} - Quét phát hiện test pass ảo, 0 assert, sleep cứng")
900
- print(f" {BOLD}4.{RESET} 🛡️ {BOLD}Verify{RESET} - Chạy kiểm tra 9 Cổng Chất Lượng DoD")
901
- print(f" {BOLD}5.{RESET} 🌐 {BOLD}Welcome{RESET} - Mở trang Landing Page trực quan")
902
- print(f" {BOLD}6.{RESET} ❓ {BOLD}Help{RESET} - Xem danh sách đầy đủ tất cả các lệnh CLI")
903
- print(f"{BOLD}{CYAN}======================================================================{RESET}")
904
- try:
905
- choice = input(f"Nhập lựa chọn {BOLD}[1-6]{RESET} (mặc định: 6): ").strip()
906
- except (EOFError, KeyboardInterrupt):
907
- print()
908
- sys.exit(0)
909
-
910
- if choice == "1":
911
- args.subcommand = "doctor"
912
- return cmd_doctor(args)
913
- elif choice == "2":
914
- args.subcommand = "setup"
915
- return cmd_setup(args)
916
- elif choice == "3":
917
- args.subcommand = "lint"
918
- return cmd_lint(args)
919
- elif choice == "4":
920
- args.subcommand = "verify"
921
- return cmd_verify(args)
922
- elif choice == "5":
923
- args.subcommand = "welcome"
924
- return cmd_welcome(args)
925
-
926
- parser.print_help()
927
- print("\n💡 Tip: Run 'npx synapse-hub welcome' (or 'npm start') to launch the visual landing page.")
928
- sys.exit(0)
996
+ return _handle_interactive_wizard(parser, args)
929
997
 
930
998
  # Enforce canonical author attribution and anti-tamper provenance
931
999
  from author_integrity import assert_integrity_or_raise
@@ -940,7 +1008,7 @@ def main():
940
1008
  import update_sentinel
941
1009
  update_sentinel.check_for_updates(force=False, notify=True)
942
1010
  except (ImportError, OSError, TimeoutError):
943
- pass
1011
+ update_status = None
944
1012
 
945
1013
  # Dispatch subcommand
946
1014
  args.func(args)