synapse-hub 2.7.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents/live-explorer.md +2 -0
- package/.agents/agents/pom-crafter.md +2 -0
- package/.agents/agents/test-runner.md +3 -0
- package/.agents/skills/lean-impact-scoreboard/SKILL.md +1 -1
- package/.agents/skills/repo-quality-audit/SKILL.md +1 -1
- package/.agents/skills/review-spec/SKILL.md +1 -1
- package/.agents/skills/senior-code-review/SKILL.md +1 -1
- package/.agents/skills/technical-debt-harvester/SKILL.md +1 -1
- package/CLAUDE.md +1 -1
- package/README.en.md +70 -291
- package/README.md +68 -303
- package/docs/ARCHITECTURE.md +48 -2
- package/docs/CONTRIBUTING.md +1 -1
- package/docs/QUALITY_GATES.md +113 -0
- package/package.json +1 -1
- package/scripts/package_dist.py +2 -1
- package/skills_manifest.json +6 -6
- package/synapse.config.json +1 -1
- package/templates/ai_bridges/CLAUDE.md +1 -1
- package/templates/ai_bridges/copilot-instructions.md +2 -2
- package/tools/__init__.py +18 -1
- package/tools/_openapi_parser.py +1 -1
- package/tools/agent_canary.py +42 -30
- package/tools/agentless_patcher.py +2 -2
- package/tools/analyze_project.py +3 -5
- package/tools/api_drift_sentinel.py +4 -4
- package/tools/api_fuzzer.py +8 -8
- package/tools/auto_heal.py +4 -5
- package/tools/auto_heal_reflexion.py +2 -2
- package/tools/autogen_qa_broker.py +2 -2
- package/tools/browser_helpers.js +2 -2
- package/tools/browsergym_eval.py +2 -3
- package/tools/bug_reporter.py +11 -13
- package/tools/bump_version.py +75 -5
- package/tools/cache_resolver.py +78 -83
- package/tools/check_env.py +9 -1
- package/tools/check_version_sync.py +40 -3
- package/tools/ci_healing_hook.py +4 -6
- package/tools/cli.py +5 -7
- package/tools/config_decoupler.py +2 -3
- package/tools/core/__init__.py +52 -0
- package/tools/count_tokens.py +22 -20
- package/tools/dashboard_generator.py +627 -998
- package/tools/db_sandbox.py +65 -53
- package/tools/debt_harvester.py +3 -3
- package/tools/distill_log.py +3 -3
- package/tools/dspy_qa_signatures.py +3 -4
- package/tools/export_postman_collection.py +8 -8
- package/tools/flaky_detector.py +2 -2
- package/tools/fuzz_payloads.py +5 -5
- package/tools/generate_allure_report.py +1 -1
- package/tools/generate_jmx_plan.py +4 -4
- package/tools/gherkin_suite.py +1 -1
- package/tools/git_pre_commit_guard.py +2 -2
- package/tools/goldfish_review.py +2 -2
- package/tools/heal/__init__.py +28 -0
- package/tools/heal_pr_automator.py +6 -6
- package/tools/heuristic_locator_matcher.py +2 -2
- package/tools/infer_linter.py +8 -8
- package/tools/interview_story.py +0 -1
- package/tools/jtl_analyzer.py +11 -11
- package/tools/lint/__init__.py +30 -0
- package/tools/lint_ai_docs.py +42 -0
- package/tools/lookup_tc.py +1 -1
- package/tools/matrix_sharder.py +15 -13
- package/tools/mcp/__init__.py +16 -0
- package/tools/mcp_excel_server.py +2 -2
- package/tools/mcp_server.py +3 -4
- package/tools/md_to_xlsx.py +26 -26
- package/tools/micro_mutator.py +11 -12
- package/tools/network_mock_shield.py +27 -27
- package/tools/newman_analyzer.py +2 -3
- package/tools/omni_emitter.py +5 -8
- package/tools/omni_parser.py +5 -5
- package/tools/omni_transpiler.py +5 -5
- package/tools/output_formatter.py +19 -0
- package/tools/perf/__init__.py +24 -0
- package/tools/pinpoint_failure.py +1 -1
- package/tools/project_state.py +0 -2
- package/tools/qa_event_stream.py +1 -1
- package/tools/repo_map.py +8 -8
- package/tools/report/__init__.py +32 -0
- package/tools/reversible_sandbox.py +1 -2
- package/tools/safety_firewall.py +2 -2
- package/tools/senior_code_review.py +2 -2
- package/tools/setup_project.py +10 -12
- package/tools/skill_collision_guard.py +3 -3
- package/tools/skill_vault.py +12 -3
- package/tools/skillspector.py +5 -7
- package/tools/smart_visual_masker.py +4 -6
- package/tools/spec_drift_sentinel.py +1 -2
- package/tools/swe_qa_aci.py +2 -2
- package/tools/synapse_qa_bench.py +3 -3
- package/tools/sync_agent_rules.py +17 -3
- package/tools/telemetry_correlator.py +3 -2
- package/tools/test_memory_os.py +15 -5
- package/tools/textgrad_mutation_optimizer.py +3 -3
- package/tools/tms_sync_bridge.py +5 -5
- package/tools/tot_exploratory_tester.py +5 -6
- package/tools/traffic_session_converter.py +9 -9
- package/tools/universal_ir.py +2 -3
- package/tools/update_sentinel.py +6 -9
- package/tools/verify_all.py +10 -0
- package/tools/visual_diff_canvas.py +1 -2
- package/tools/visual_som_helper.py +15 -13
- package/tools/watch_mode.py +1 -1
- package/tools/wcag_audit.py +22 -1
- package/tools/welcome_page.py +5 -6
package/tools/ci_healing_hook.py
CHANGED
|
@@ -10,10 +10,8 @@ When a test fails due to a broken locator:
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import os
|
|
13
|
-
import sys
|
|
14
|
-
import json
|
|
15
13
|
import argparse
|
|
16
|
-
from typing import Dict, Any
|
|
14
|
+
from typing import Dict, Any
|
|
17
15
|
from datetime import datetime
|
|
18
16
|
|
|
19
17
|
|
|
@@ -35,11 +33,11 @@ class CIHealingHook:
|
|
|
35
33
|
"""
|
|
36
34
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
37
35
|
branch_name = f"auto-heal/{test_id.lower()}_{timestamp}"
|
|
38
|
-
|
|
36
|
+
|
|
39
37
|
pr_description = f"""## 🤖 Autonomous CI/CD Self-Healing Report
|
|
40
38
|
|
|
41
|
-
> **Target File:** `{file_path}`
|
|
42
|
-
> **Confidence Score:** `{confidence * 100:.1f}%`
|
|
39
|
+
> **Target File:** `{file_path}`
|
|
40
|
+
> **Confidence Score:** `{confidence * 100:.1f}%`
|
|
43
41
|
> **Timestamp:** `{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}`
|
|
44
42
|
|
|
45
43
|
### 📝 Summary of Changes
|
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 = "
|
|
44
|
+
version = "3.0.0"
|
|
45
45
|
if os.path.exists(manifest_path):
|
|
46
46
|
try:
|
|
47
47
|
import json
|
|
@@ -145,7 +145,7 @@ def cmd_clean(args):
|
|
|
145
145
|
os.remove(os.path.join(root, f))
|
|
146
146
|
removed_count += 1
|
|
147
147
|
except OSError as err:
|
|
148
|
-
|
|
148
|
+
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
|
|
|
@@ -255,7 +255,6 @@ def cmd_transpile(args):
|
|
|
255
255
|
def cmd_omni_scan(args):
|
|
256
256
|
from omni_transpiler import scan_repository
|
|
257
257
|
inv = scan_repository(args.path)
|
|
258
|
-
import json
|
|
259
258
|
if getattr(args, "json", False):
|
|
260
259
|
print(json.dumps(inv, indent=2))
|
|
261
260
|
else:
|
|
@@ -542,21 +541,20 @@ def cmd_release(args):
|
|
|
542
541
|
|
|
543
542
|
def _hub_version():
|
|
544
543
|
manifest_path = os.path.join(REPO_ROOT, "skills_manifest.json")
|
|
545
|
-
version = "
|
|
544
|
+
version = "3.0.0"
|
|
546
545
|
if os.path.exists(manifest_path):
|
|
547
546
|
try:
|
|
548
547
|
import json
|
|
549
548
|
with open(manifest_path, "r", encoding="utf-8") as f:
|
|
550
549
|
version = json.load(f).get("version", version)
|
|
551
550
|
except (OSError, json.JSONDecodeError):
|
|
552
|
-
version = "
|
|
551
|
+
version = "3.0.0"
|
|
553
552
|
return version
|
|
554
553
|
|
|
555
554
|
|
|
556
555
|
class SynapseArgumentParser(argparse.ArgumentParser):
|
|
557
556
|
"""Enhanced ArgumentParser providing fuzzy Did-You-Mean suggestions on command typos."""
|
|
558
557
|
def error(self, message):
|
|
559
|
-
import difflib
|
|
560
558
|
m = re.search(r"invalid choice: '([^']+)'", message)
|
|
561
559
|
if m:
|
|
562
560
|
bad_choice = m.group(1)
|
|
@@ -1008,7 +1006,7 @@ def main():
|
|
|
1008
1006
|
import update_sentinel
|
|
1009
1007
|
update_sentinel.check_for_updates(force=False, notify=True)
|
|
1010
1008
|
except (ImportError, OSError, TimeoutError):
|
|
1011
|
-
|
|
1009
|
+
_ = False
|
|
1012
1010
|
|
|
1013
1011
|
# Dispatch subcommand
|
|
1014
1012
|
args.func(args)
|
|
@@ -15,8 +15,7 @@ import re
|
|
|
15
15
|
import sys
|
|
16
16
|
import json
|
|
17
17
|
import argparse
|
|
18
|
-
from
|
|
19
|
-
from typing import Dict, List, Any, Tuple
|
|
18
|
+
from typing import Dict, List, Any, Tuple, Optional
|
|
20
19
|
|
|
21
20
|
# Enforce UTF-8 stdout encoding for Windows console compatibility
|
|
22
21
|
if hasattr(sys.stdout, 'reconfigure'):
|
|
@@ -129,7 +128,7 @@ class ConfigDecoupler:
|
|
|
129
128
|
"replacement": f"process.env.{key}"
|
|
130
129
|
})
|
|
131
130
|
|
|
132
|
-
def export_configs(self, output_dir: str = None) -> Tuple[str, str]:
|
|
131
|
+
def export_configs(self, output_dir: Optional[str] = None) -> Tuple[str, str]:
|
|
133
132
|
"""Generates env.default.json and .env.example configuration files."""
|
|
134
133
|
out_base = output_dir or os.path.join(self.target_dir, "config", "profiles")
|
|
135
134
|
os.makedirs(out_base, exist_ok=True)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Synapse Hub — Core Execution Engines & Verification Sentinels (tools.core)
|
|
3
|
+
--------------------------------------------------------------------------
|
|
4
|
+
Domain package grouping all CLI routers, Definition-of-Done Quality Gate
|
|
5
|
+
orchestrators, AST scanners, and autonomous subagent execution bridges.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from tools import (
|
|
9
|
+
analyze_project,
|
|
10
|
+
bump_version,
|
|
11
|
+
check_env,
|
|
12
|
+
cli,
|
|
13
|
+
count_tokens,
|
|
14
|
+
debt_harvester,
|
|
15
|
+
distill_log,
|
|
16
|
+
micro_mutator,
|
|
17
|
+
project_state,
|
|
18
|
+
repo_map,
|
|
19
|
+
safety_firewall,
|
|
20
|
+
senior_code_review,
|
|
21
|
+
setup_project,
|
|
22
|
+
skill_vault,
|
|
23
|
+
sync_agent_rules,
|
|
24
|
+
test_impact,
|
|
25
|
+
test_memory_os,
|
|
26
|
+
universal_ir,
|
|
27
|
+
update_sentinel,
|
|
28
|
+
verify_all,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"analyze_project",
|
|
33
|
+
"bump_version",
|
|
34
|
+
"check_env",
|
|
35
|
+
"cli",
|
|
36
|
+
"count_tokens",
|
|
37
|
+
"debt_harvester",
|
|
38
|
+
"distill_log",
|
|
39
|
+
"micro_mutator",
|
|
40
|
+
"project_state",
|
|
41
|
+
"repo_map",
|
|
42
|
+
"safety_firewall",
|
|
43
|
+
"senior_code_review",
|
|
44
|
+
"setup_project",
|
|
45
|
+
"skill_vault",
|
|
46
|
+
"sync_agent_rules",
|
|
47
|
+
"test_impact",
|
|
48
|
+
"test_memory_os",
|
|
49
|
+
"universal_ir",
|
|
50
|
+
"update_sentinel",
|
|
51
|
+
"verify_all",
|
|
52
|
+
]
|
package/tools/count_tokens.py
CHANGED
|
@@ -39,9 +39,9 @@ import hashlib
|
|
|
39
39
|
import sqlite3
|
|
40
40
|
import argparse
|
|
41
41
|
from datetime import datetime, timezone, timedelta
|
|
42
|
-
from typing import Dict, List, Any, Optional
|
|
42
|
+
from typing import Dict, List, Any, Optional
|
|
43
43
|
|
|
44
|
-
PRICING_TABLE = {
|
|
44
|
+
PRICING_TABLE: Dict[str, Dict[str, Any]] = {
|
|
45
45
|
"gemini-flash": {
|
|
46
46
|
"name": "Google Gemini 2.5/3.x Flash",
|
|
47
47
|
"input_per_m": 0.075,
|
|
@@ -140,7 +140,7 @@ def get_budget_config() -> Dict[str, int]:
|
|
|
140
140
|
"budget_7d": data.get("budget_7d", DEFAULT_7D_BUDGET),
|
|
141
141
|
}
|
|
142
142
|
except (OSError, json.JSONDecodeError):
|
|
143
|
-
|
|
143
|
+
_ = False
|
|
144
144
|
return {
|
|
145
145
|
"budget_5h": DEFAULT_5H_BUDGET,
|
|
146
146
|
"budget_7d": DEFAULT_7D_BUDGET,
|
|
@@ -198,17 +198,19 @@ class AntigravityAdapter:
|
|
|
198
198
|
if db_path:
|
|
199
199
|
try:
|
|
200
200
|
conn = sqlite3.connect(db_path)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
201
|
+
try:
|
|
202
|
+
cursor = conn.cursor()
|
|
203
|
+
cursor.execute("SELECT conversation_id, title, step_count, last_modified_time FROM conversation_summaries")
|
|
204
|
+
for row in cursor.fetchall():
|
|
205
|
+
title_map[row[0]] = {
|
|
206
|
+
"title": row[1],
|
|
207
|
+
"step_count": row[2],
|
|
208
|
+
"last_modified": row[3],
|
|
209
|
+
}
|
|
210
|
+
finally:
|
|
211
|
+
conn.close()
|
|
210
212
|
except (sqlite3.Error, OSError):
|
|
211
|
-
|
|
213
|
+
_ = False
|
|
212
214
|
|
|
213
215
|
conversations = []
|
|
214
216
|
for entry in os.listdir(brain_dir):
|
|
@@ -240,7 +242,7 @@ class AntigravityAdapter:
|
|
|
240
242
|
return {"error": f"Transcript not found at {transcript_path}"}
|
|
241
243
|
|
|
242
244
|
turns = []
|
|
243
|
-
current_turn = None
|
|
245
|
+
current_turn: Optional[Dict[str, Any]] = None
|
|
244
246
|
total_input = 0
|
|
245
247
|
total_cache = 0
|
|
246
248
|
total_output = 0
|
|
@@ -388,7 +390,7 @@ class AntigravityAdapter:
|
|
|
388
390
|
usage_hours["cache"] += cache_tok
|
|
389
391
|
usage_hours["output"] += out_tok
|
|
390
392
|
except (OSError, UnicodeDecodeError):
|
|
391
|
-
|
|
393
|
+
_ = False
|
|
392
394
|
|
|
393
395
|
budgets = get_budget_config()
|
|
394
396
|
b_5h = budgets["budget_5h"]
|
|
@@ -452,7 +454,7 @@ class CursorAdapter:
|
|
|
452
454
|
return []
|
|
453
455
|
|
|
454
456
|
pattern = os.path.join(projects_dir, "*", "agent-transcripts", "*", "*.jsonl")
|
|
455
|
-
sessions = []
|
|
457
|
+
sessions: List[Dict[str, Any]] = []
|
|
456
458
|
for fpath in glob.glob(pattern):
|
|
457
459
|
try:
|
|
458
460
|
mtime = os.path.getmtime(fpath)
|
|
@@ -493,7 +495,7 @@ class CursorAdapter:
|
|
|
493
495
|
return {"error": f"Transcript not found at {transcript_path}"}
|
|
494
496
|
|
|
495
497
|
turns = []
|
|
496
|
-
current_turn = None
|
|
498
|
+
current_turn: Optional[Dict[str, Any]] = None
|
|
497
499
|
total_input = 0
|
|
498
500
|
total_output = 0
|
|
499
501
|
total_cache = 0
|
|
@@ -608,7 +610,7 @@ class ClaudeCodeAdapter:
|
|
|
608
610
|
|
|
609
611
|
@classmethod
|
|
610
612
|
def get_sessions(cls) -> List[Dict[str, Any]]:
|
|
611
|
-
sessions = []
|
|
613
|
+
sessions: List[Dict[str, Any]] = []
|
|
612
614
|
home = os.path.expanduser("~")
|
|
613
615
|
# Search candidate directories
|
|
614
616
|
patterns = [
|
|
@@ -665,7 +667,7 @@ def detect_platform_from_file(file_path: str) -> str:
|
|
|
665
667
|
if "claude" in line.lower():
|
|
666
668
|
return "claude"
|
|
667
669
|
except (OSError, UnicodeDecodeError):
|
|
668
|
-
|
|
670
|
+
_ = False
|
|
669
671
|
return "antigravity"
|
|
670
672
|
|
|
671
673
|
|
|
@@ -997,7 +999,7 @@ def export_opentelemetry_genai_spans(parsed: Dict[str, Any], session_id: str = "
|
|
|
997
999
|
}
|
|
998
1000
|
gen_ai_system = system_map.get(platform, "google")
|
|
999
1001
|
|
|
1000
|
-
spans = []
|
|
1002
|
+
spans: List[Dict[str, Any]] = []
|
|
1001
1003
|
turns = parsed.get("turns", [])
|
|
1002
1004
|
for idx, turn in enumerate(turns, 1):
|
|
1003
1005
|
turn_span_id = hashlib.md5(f"{session_id}_turn_{idx}".encode('utf-8'), usedforsecurity=False).hexdigest()[:16]
|