synapse-hub 2.1.0 → 2.2.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/orchestrator.md +7 -0
- package/.agents/rules/lessons-learned.md +1 -0
- package/.agents/skills/agent-orchestration-multi-agent-optimize/SKILL.md +1 -1
- package/.agents/skills/antigravity-test-sentinel/SKILL.md +1 -2
- package/.agents/skills/api-network-mocking-interception/SKILL.md +1 -1
- package/.agents/skills/api-spec-to-e2e-matrix/SKILL.md +11 -4
- package/.agents/skills/architecture-decision-records/SKILL.md +1 -1
- package/.agents/skills/auth-session-and-cookie-manager/SKILL.md +1 -1
- package/.agents/skills/backend-load-and-stress-patterns/SKILL.md +32 -11
- package/.agents/skills/bats-testing-patterns/SKILL.md +1 -1
- package/.agents/skills/clean-pom-crafter/SKILL.md +1 -4
- package/.agents/skills/code-refactoring-refactor-clean/SKILL.md +1 -1
- package/.agents/skills/db-state-verifier-and-seeder/SKILL.md +1 -1
- package/.agents/skills/e2e-testing-patterns/SKILL.md +1 -1
- package/.agents/skills/failure-autopsy-and-healing/SKILL.md +1 -3
- package/.agents/skills/file-and-report-validator/SKILL.md +1 -1
- package/.agents/skills/flaky-test-sentinel-and-quarantine/SKILL.md +1 -1
- package/.agents/skills/github-actions-templates/SKILL.md +1 -1
- package/.agents/skills/graphify-impact-analyzer/SKILL.md +1 -3
- package/.agents/skills/katalon-cli-runner/SKILL.md +1 -1
- package/.agents/skills/lam-script-generator/SKILL.md +1 -2
- package/.agents/skills/playwright-live-interaction/SKILL.md +1 -4
- package/.agents/skills/security-dast-sentinel/SKILL.md +1 -1
- package/.agents/skills/self-healing-locator/SKILL.md +1 -2
- package/.agents/skills/skillspector-security-guard/SKILL.md +115 -0
- package/.agents/skills/synthetic-test-data-generator/SKILL.md +1 -1
- package/.agents/skills/token-and-context-optimizer/SKILL.md +1 -1
- package/.agents/skills/visual-regression-sentinel/SKILL.md +1 -1
- package/.agents/skills/wcag-audit-patterns/SKILL.md +1 -1
- package/.agents/skills/web-vitals-and-performance-profiler/SKILL.md +1 -1
- package/AGENTS.md +36 -0
- package/README.md +140 -103
- package/package.json +1 -1
- package/skills_manifest.json +42 -29
- package/templates/PROJECT_AI_GUIDE_TEMPLATE.md +15 -1
- package/templates/ai_bridges/CLAUDE.md +31 -0
- package/templates/ai_bridges/copilot-instructions.md +25 -0
- package/templates/ai_bridges/cursor_synapse_qa.mdc +26 -0
- package/templates/ai_bridges/windsurfrules +25 -0
- package/templates/ci/github-actions-synapse.yml +28 -0
- package/templates/ci/gitlab-ci-synapse.yml +16 -0
- package/tools/TOOLS_RUNBOOK.md +203 -12
- package/tools/browser_helpers.js +2 -2
- package/tools/bump_version.py +8 -0
- package/tools/cli.py +74 -2
- package/tools/export_postman_collection.py +535 -218
- package/tools/generate_jmx_plan.py +672 -102
- package/tools/git_pre_commit_guard.py +21 -0
- package/tools/jtl_analyzer.py +474 -0
- package/tools/mcp_excel_server.ps1 +1 -1
- package/tools/mcp_server.py +1 -1
- package/tools/newman_analyzer.py +385 -0
- package/tools/setup_project.py +203 -18
- package/tools/skillspector.py +1141 -0
- package/tools/telemetry_correlator.py +351 -0
- package/tools/templates/jmeter-distributed/README.md +54 -0
- package/tools/templates/jmeter-distributed/docker-compose.yml +83 -0
- package/tools/update_sentinel.py +313 -0
- package/tools/repo_map.json +0 -12
- package/tools/repo_map.txt +0 -7
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Enterprise Synapse-Hub Auto-Update & Version Drift Sentinel
|
|
4
|
+
------------------------------------------------------------
|
|
5
|
+
Provides non-blocking upstream version checks and 1-click self-updating
|
|
6
|
+
across Local Git Clones, Global Antigravity Plugins, and NPM installations.
|
|
7
|
+
|
|
8
|
+
Features:
|
|
9
|
+
1. Non-blocking check against NPM Registry & GitHub (cached 24h, zero latency).
|
|
10
|
+
2. Non-intrusive update banner on CLI invocations.
|
|
11
|
+
3. 1-Click upgrade engine: `synapse-hub update` / `agent-qa update`.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
import json
|
|
17
|
+
import time
|
|
18
|
+
import urllib.request
|
|
19
|
+
import subprocess
|
|
20
|
+
from datetime import datetime
|
|
21
|
+
|
|
22
|
+
# Enforce UTF-8 stdout encoding for Windows console compatibility
|
|
23
|
+
if hasattr(sys.stdout, 'reconfigure'):
|
|
24
|
+
try:
|
|
25
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
26
|
+
sys.stderr.reconfigure(encoding='utf-8')
|
|
27
|
+
except Exception:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
31
|
+
HUB_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
|
|
32
|
+
GLOBAL_DIR = os.path.expanduser("~/.agent_memory")
|
|
33
|
+
CACHE_FILE = os.path.join(GLOBAL_DIR, "update_cache.json")
|
|
34
|
+
GLOBAL_PLUGIN_DIR = os.path.expanduser("~/.gemini/config/plugins/synapse-hub")
|
|
35
|
+
|
|
36
|
+
CHECK_INTERVAL_SECONDS = 86400 # 24 Hours
|
|
37
|
+
|
|
38
|
+
# ANSI Formatting
|
|
39
|
+
CYAN = "\033[96m"
|
|
40
|
+
GREEN = "\033[92m"
|
|
41
|
+
YELLOW = "\033[93m"
|
|
42
|
+
RED = "\033[91m"
|
|
43
|
+
BOLD = "\033[1m"
|
|
44
|
+
RESET = "\033[0m"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def parse_semver(ver_str):
|
|
48
|
+
"""Parses a version string into a numeric tuple for comparison."""
|
|
49
|
+
clean = ver_str.strip().lstrip("v")
|
|
50
|
+
parts = []
|
|
51
|
+
for p in clean.split("."):
|
|
52
|
+
try:
|
|
53
|
+
parts.append(int(p))
|
|
54
|
+
except ValueError:
|
|
55
|
+
parts.append(0)
|
|
56
|
+
while len(parts) < 3:
|
|
57
|
+
parts.append(0)
|
|
58
|
+
return tuple(parts[:3])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_local_version():
|
|
62
|
+
"""Reads the local version from package.json or skills_manifest.json."""
|
|
63
|
+
pkg_file = os.path.join(HUB_ROOT, "package.json")
|
|
64
|
+
if os.path.exists(pkg_file):
|
|
65
|
+
try:
|
|
66
|
+
with open(pkg_file, "r", encoding="utf-8") as f:
|
|
67
|
+
data = json.load(f)
|
|
68
|
+
return data.get("version", "2.1.1")
|
|
69
|
+
except Exception:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
manifest_file = os.path.join(HUB_ROOT, "skills_manifest.json")
|
|
73
|
+
if os.path.exists(manifest_file):
|
|
74
|
+
try:
|
|
75
|
+
with open(manifest_file, "r", encoding="utf-8") as f:
|
|
76
|
+
data = json.load(f)
|
|
77
|
+
return data.get("version", "2.1.1")
|
|
78
|
+
except Exception:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
return "2.1.1"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def fetch_remote_version():
|
|
85
|
+
"""Queries NPM registry or GitHub raw for the latest published version."""
|
|
86
|
+
headers = {"User-Agent": "synapse-hub-update-sentinel"}
|
|
87
|
+
|
|
88
|
+
# 1. Primary: NPM Registry
|
|
89
|
+
try:
|
|
90
|
+
req = urllib.request.Request("https://registry.npmjs.org/synapse-hub/latest", headers=headers)
|
|
91
|
+
with urllib.request.urlopen(req, timeout=1.8) as resp:
|
|
92
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
93
|
+
if "version" in data:
|
|
94
|
+
return data["version"], "npm"
|
|
95
|
+
except Exception:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
# 2. Secondary fallback: GitHub raw package.json
|
|
99
|
+
try:
|
|
100
|
+
raw_url = "https://raw.githubusercontent.com/TeeVee998/Synapse-Hub/main/package.json"
|
|
101
|
+
req = urllib.request.Request(raw_url, headers=headers)
|
|
102
|
+
with urllib.request.urlopen(req, timeout=1.8) as resp:
|
|
103
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
104
|
+
if "version" in data:
|
|
105
|
+
return data["version"], "github"
|
|
106
|
+
except Exception:
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
return None, None
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def read_update_cache():
|
|
113
|
+
if os.path.exists(CACHE_FILE):
|
|
114
|
+
try:
|
|
115
|
+
with open(CACHE_FILE, "r", encoding="utf-8") as f:
|
|
116
|
+
return json.load(f)
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
return {}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def write_update_cache(data):
|
|
123
|
+
try:
|
|
124
|
+
os.makedirs(GLOBAL_DIR, exist_ok=True)
|
|
125
|
+
with open(CACHE_FILE, "w", encoding="utf-8") as f:
|
|
126
|
+
json.dump(data, f, indent=2)
|
|
127
|
+
except Exception:
|
|
128
|
+
pass
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def check_for_updates(force=False, notify=True):
|
|
132
|
+
"""
|
|
133
|
+
Checks if a newer version exists upstream.
|
|
134
|
+
Uses a 24-hour file cache to prevent network overhead during daily workflows.
|
|
135
|
+
"""
|
|
136
|
+
cache = read_update_cache()
|
|
137
|
+
now = time.time()
|
|
138
|
+
last_check = cache.get("last_check_timestamp", 0)
|
|
139
|
+
|
|
140
|
+
local_ver = get_local_version()
|
|
141
|
+
remote_ver = cache.get("latest_remote_version")
|
|
142
|
+
|
|
143
|
+
# Only fetch if cache is stale or forced
|
|
144
|
+
if force or (now - last_check > CHECK_INTERVAL_SECONDS) or not remote_ver:
|
|
145
|
+
fetched_ver, source = fetch_remote_version()
|
|
146
|
+
if fetched_ver:
|
|
147
|
+
remote_ver = fetched_ver
|
|
148
|
+
cache["latest_remote_version"] = fetched_ver
|
|
149
|
+
cache["source"] = source
|
|
150
|
+
cache["last_check_timestamp"] = now
|
|
151
|
+
cache["last_check_date"] = datetime.now().isoformat()
|
|
152
|
+
write_update_cache(cache)
|
|
153
|
+
elif not remote_ver:
|
|
154
|
+
return False, local_ver, None
|
|
155
|
+
|
|
156
|
+
if remote_ver:
|
|
157
|
+
is_newer = parse_semver(remote_ver) > parse_semver(local_ver)
|
|
158
|
+
if is_newer and notify:
|
|
159
|
+
print_update_banner(local_ver, remote_ver)
|
|
160
|
+
return is_newer, local_ver, remote_ver
|
|
161
|
+
|
|
162
|
+
return False, local_ver, None
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def print_update_banner(local_ver, remote_ver):
|
|
166
|
+
"""Prints a clean ASCII alert banner when an update is available."""
|
|
167
|
+
banner = f"""
|
|
168
|
+
{CYAN}┌────────────────────────────────────────────────────────────────────────┐
|
|
169
|
+
│ {BOLD}🚀 Synapse-Hub Update Available: {YELLOW}{local_ver}{RESET}{CYAN} → {GREEN}{BOLD}v{remote_ver}{RESET}{CYAN} │
|
|
170
|
+
│ │
|
|
171
|
+
│ To upgrade your local hub, run: │
|
|
172
|
+
│ 👉 {BOLD}agent-qa update{RESET}{CYAN} or {BOLD}npx synapse-hub update{RESET}{CYAN} │
|
|
173
|
+
│ │
|
|
174
|
+
│ Repository: {BOLD}https://github.com/TeeVee998/Synapse-Hub{RESET}{CYAN} │
|
|
175
|
+
└────────────────────────────────────────────────────────────────────────┘{RESET}
|
|
176
|
+
"""
|
|
177
|
+
print(banner)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def perform_update():
|
|
181
|
+
"""
|
|
182
|
+
Executes 1-click update:
|
|
183
|
+
1. If inside a git repository (local clone or global plugin): pulls latest changes.
|
|
184
|
+
2. Synchronizes SQLite central memory.
|
|
185
|
+
3. Re-runs DoD Quality Gates to guarantee integrity.
|
|
186
|
+
"""
|
|
187
|
+
print(f"\n{BOLD}{CYAN}======================================================================{RESET}")
|
|
188
|
+
print(f"{BOLD}{CYAN} SYNAPSE-HUB: 1-CLICK AUTOMATED UPDATE ENGINE {RESET}")
|
|
189
|
+
print(f"{BOLD}{CYAN}======================================================================{RESET}")
|
|
190
|
+
|
|
191
|
+
local_ver = get_local_version()
|
|
192
|
+
print(f"📦 Current Hub Version: {BOLD}v{local_ver}{RESET}")
|
|
193
|
+
print("🔍 Checking upstream for latest releases...")
|
|
194
|
+
|
|
195
|
+
has_update, local_ver, remote_ver = check_for_updates(force=True, notify=False)
|
|
196
|
+
if remote_ver:
|
|
197
|
+
print(f"🌐 Latest Upstream Version: {BOLD}{GREEN}v{remote_ver}{RESET}")
|
|
198
|
+
else:
|
|
199
|
+
print("⚠️ Could not reach upstream registry (offline or network timeout).")
|
|
200
|
+
|
|
201
|
+
# Detect if repo is a git clone
|
|
202
|
+
git_dir = os.path.join(HUB_ROOT, ".git")
|
|
203
|
+
is_git_repo = os.path.exists(git_dir)
|
|
204
|
+
|
|
205
|
+
updated = False
|
|
206
|
+
|
|
207
|
+
if is_git_repo:
|
|
208
|
+
print(f"\n{BOLD}[1/3] Pulling latest updates via Git...{RESET}")
|
|
209
|
+
try:
|
|
210
|
+
res = subprocess.run(
|
|
211
|
+
["git", "pull", "--ff-only"],
|
|
212
|
+
cwd=HUB_ROOT,
|
|
213
|
+
stdout=subprocess.PIPE,
|
|
214
|
+
stderr=subprocess.PIPE,
|
|
215
|
+
text=True
|
|
216
|
+
)
|
|
217
|
+
if res.returncode == 0:
|
|
218
|
+
print(f" {GREEN}[OK] Git pull successful:{RESET}")
|
|
219
|
+
for line in res.stdout.strip().splitlines():
|
|
220
|
+
print(f" {line}")
|
|
221
|
+
updated = True
|
|
222
|
+
else:
|
|
223
|
+
print(f" ⚠️ Git pull notice: {res.stderr.strip() or res.stdout.strip()}")
|
|
224
|
+
except Exception as e:
|
|
225
|
+
print(f" ⚠️ Could not execute git pull: {e}")
|
|
226
|
+
else:
|
|
227
|
+
print(f"\n{BOLD}[1/3] Checking NPM package installation...{RESET}")
|
|
228
|
+
try:
|
|
229
|
+
res = subprocess.run(
|
|
230
|
+
["npm", "install", "-g", "synapse-hub@latest"],
|
|
231
|
+
stdout=subprocess.PIPE,
|
|
232
|
+
stderr=subprocess.PIPE,
|
|
233
|
+
text=True
|
|
234
|
+
)
|
|
235
|
+
if res.returncode == 0:
|
|
236
|
+
print(f" {GREEN}[OK] Global NPM package updated to latest!{RESET}")
|
|
237
|
+
updated = True
|
|
238
|
+
except Exception:
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
# 2. Check Global Plugin
|
|
242
|
+
if os.path.exists(GLOBAL_PLUGIN_DIR) and GLOBAL_PLUGIN_DIR.lower() != HUB_ROOT.lower():
|
|
243
|
+
print(f"\n{BOLD}[2/3] Synchronizing Global Antigravity Plugin...{RESET}")
|
|
244
|
+
plugin_git = os.path.join(GLOBAL_PLUGIN_DIR, ".git")
|
|
245
|
+
if os.path.exists(plugin_git):
|
|
246
|
+
try:
|
|
247
|
+
subprocess.run(["git", "pull", "--ff-only"], cwd=GLOBAL_PLUGIN_DIR, stdout=subprocess.DEVNULL)
|
|
248
|
+
print(f" {GREEN}[OK] Updated Global Plugin repository: {GLOBAL_PLUGIN_DIR}{RESET}")
|
|
249
|
+
except Exception:
|
|
250
|
+
pass
|
|
251
|
+
else:
|
|
252
|
+
# Refresh plugin.json in global plugin
|
|
253
|
+
try:
|
|
254
|
+
import shutil
|
|
255
|
+
src_pkg = os.path.join(HUB_ROOT, "plugin.json")
|
|
256
|
+
dst_pkg = os.path.join(GLOBAL_PLUGIN_DIR, "plugin.json")
|
|
257
|
+
if os.path.exists(src_pkg):
|
|
258
|
+
shutil.copy2(src_pkg, dst_pkg)
|
|
259
|
+
print(f" {GREEN}[OK] Refreshed plugin.json in: {GLOBAL_PLUGIN_DIR}{RESET}")
|
|
260
|
+
except Exception:
|
|
261
|
+
pass
|
|
262
|
+
|
|
263
|
+
# 3. Re-initialize SQLite Memory Cache
|
|
264
|
+
print(f"\n{BOLD}[3/3] Synchronizing Central Agent Memory Cache...{RESET}")
|
|
265
|
+
try:
|
|
266
|
+
import cache_resolver
|
|
267
|
+
cache_resolver.init_db(seed=True)
|
|
268
|
+
print(f" {GREEN}[OK] Synced episodic solution memory (0-token cache).{RESET}")
|
|
269
|
+
except Exception as e:
|
|
270
|
+
print(f" ⚠️ Cache sync notice: {e}")
|
|
271
|
+
|
|
272
|
+
# Clear update cache so banner dismisses
|
|
273
|
+
new_local_ver = get_local_version()
|
|
274
|
+
cache = {
|
|
275
|
+
"last_check_timestamp": time.time(),
|
|
276
|
+
"latest_remote_version": new_local_ver,
|
|
277
|
+
"last_check_date": datetime.now().isoformat(),
|
|
278
|
+
"source": "self-update"
|
|
279
|
+
}
|
|
280
|
+
write_update_cache(cache)
|
|
281
|
+
|
|
282
|
+
print(f"\n{BOLD}{CYAN}======================================================================{RESET}")
|
|
283
|
+
print(f"{BOLD}{GREEN} 🎉 UPDATE COMPLETE: Synapse-Hub is up to date (v{new_local_ver})! {RESET}")
|
|
284
|
+
print(f"{BOLD}{CYAN}======================================================================{RESET}\n")
|
|
285
|
+
return True
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def main():
|
|
289
|
+
import argparse
|
|
290
|
+
parser = argparse.ArgumentParser(description="Synapse-Hub Auto-Update & Drift Sentinel")
|
|
291
|
+
parser.add_argument("--check", action="store_true", help="Check for available updates without applying")
|
|
292
|
+
parser.add_argument("--update", action="store_true", help="Perform 1-click update to latest version")
|
|
293
|
+
parser.add_argument("--force", action="store_true", help="Force refresh update check bypassing cache")
|
|
294
|
+
args = parser.parse_args()
|
|
295
|
+
|
|
296
|
+
if args.check:
|
|
297
|
+
has_update, cur, rem = check_for_updates(force=True, notify=False)
|
|
298
|
+
print(f"Current Hub Version : v{cur}")
|
|
299
|
+
print(f"Latest Upstream : v{rem if rem else 'Unknown'}")
|
|
300
|
+
if has_update:
|
|
301
|
+
print(f"{YELLOW}⚠️ An update is available! Run 'agent-qa update' to upgrade.{RESET}")
|
|
302
|
+
sys.exit(1)
|
|
303
|
+
else:
|
|
304
|
+
print(f"{GREEN}✅ Synapse-Hub is up to date.{RESET}")
|
|
305
|
+
sys.exit(0)
|
|
306
|
+
|
|
307
|
+
if args.update or not (args.check or args.force):
|
|
308
|
+
perform_update()
|
|
309
|
+
sys.exit(0)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
if __name__ == "__main__":
|
|
313
|
+
main()
|
package/tools/repo_map.json
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"generated_at": "2026-10-29 21:59:04",
|
|
3
|
-
"target_repository": "/Users/phungcao/Documents/Agent Skill",
|
|
4
|
-
"classes_count": 0,
|
|
5
|
-
"methods_count": 0,
|
|
6
|
-
"source_lines": 0,
|
|
7
|
-
"raw_bytes": 0,
|
|
8
|
-
"compressed_bytes": 442,
|
|
9
|
-
"compression_ratio_pct": -44100.0,
|
|
10
|
-
"estimated_tokens": 110,
|
|
11
|
-
"classes": []
|
|
12
|
-
}
|
package/tools/repo_map.txt
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# ==============================================================================
|
|
2
|
-
# ENTERPRISE AUTOMATION REPOSITORY MAP (Aider-Style AST Compression)
|
|
3
|
-
# Generated : 2026-10-29 21:59:04
|
|
4
|
-
# Target : /Users/phungcao/Documents/Agent Skill
|
|
5
|
-
# Scope : 0 Classes (0 source lines, 0.0 KB)
|
|
6
|
-
# Purpose : Token-budgeted index (< 600 tokens) for instant method lookup
|
|
7
|
-
# ==============================================================================
|