torusguard 0.9.4 → 1.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/.torusguard/.manifest.json +15 -10
- package/.torusguard/config/torusguard.json +1 -1
- package/.torusguard/schemas/memory-context.schema.json +95 -0
- package/.torusguard/schemas/memory-event.schema.json +70 -0
- package/.torusguard/schemas/memory-pattern.schema.json +65 -0
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
- package/.torusguard/scripts/diff_guard.py +71 -11
- package/.torusguard/scripts/finding_scorer.py +171 -86
- package/.torusguard/scripts/manifest_builder.py +2 -0
- package/.torusguard/scripts/memory_engine.py +912 -0
- package/.torusguard/scripts/run_manager.py +171 -89
- package/.torusguard/skills/torusguard/SKILL.md +12 -7
- package/.torusguard/skills/torusguard/bootstrap.py +344 -56
- package/.torusguard/skills/torusguard-audit/SKILL.md +25 -25
- package/.torusguard/skills/torusguard-harden/SKILL.md +3 -3
- package/.torusguard/skills/torusguard-recheck/SKILL.md +3 -3
- package/.torusguard/workflows/memory.md +53 -0
- package/README.md +12 -2
- package/bin/torusguard.js +173 -43
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +4 -3
- package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
- package/skills/torusguard/bootstrap.py +244 -80
- package/skills/torusguard/payload/.manifest.json +15 -10
- package/skills/torusguard/payload/config/torusguard.json +1 -1
- package/skills/torusguard/payload/schemas/memory-context.schema.json +95 -0
- package/skills/torusguard/payload/schemas/memory-event.schema.json +70 -0
- package/skills/torusguard/payload/schemas/memory-pattern.schema.json +65 -0
- package/skills/torusguard/payload/scripts/diff_guard.py +71 -11
- package/skills/torusguard/payload/scripts/finding_scorer.py +171 -86
- package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
- package/skills/torusguard/payload/scripts/memory_engine.py +912 -0
- package/skills/torusguard/payload/scripts/run_manager.py +171 -89
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +12 -7
- package/skills/torusguard/payload/skills/torusguard/bootstrap.py +344 -56
- package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +25 -25
- package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +3 -3
- package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +3 -3
- package/skills/torusguard/payload/workflows/memory.md +53 -0
- package/skills/torusguard-audit/SKILL.md +25 -25
- package/skills/torusguard-harden/SKILL.md +3 -3
- package/skills/torusguard-recheck/SKILL.md +3 -3
|
@@ -1,86 +1,171 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
TorusGuard
|
|
4
|
-
Evaluates finding confidence against the objective 0–100 scoring model
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TorusGuard Finding Confidence Scorer (v1.0.0)
|
|
4
|
+
Evaluates finding confidence against the objective 0–100 scoring model,
|
|
5
|
+
augmented by persistent memory patterns and false-positive suppression.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import argparse
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, Any, Tuple, Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def compute_memory_boost(
|
|
16
|
+
rule_id: str,
|
|
17
|
+
file_path: Optional[str] = None,
|
|
18
|
+
root_dir: Optional[Path] = None
|
|
19
|
+
) -> int:
|
|
20
|
+
"""
|
|
21
|
+
Query .torusguard/memory/patterns.json to calculate memory confidence modifier:
|
|
22
|
+
- False positive class: -30 (heavily suppressed)
|
|
23
|
+
- Regression watch: +15 (high alert / known recurrence)
|
|
24
|
+
- Recurring fix / Common vulnerability: +10
|
|
25
|
+
- Security idiom: +5
|
|
26
|
+
- Multi-file pattern match bonus: +5
|
|
27
|
+
"""
|
|
28
|
+
if not rule_id:
|
|
29
|
+
return 0
|
|
30
|
+
|
|
31
|
+
base = Path(root_dir or Path.cwd()).resolve()
|
|
32
|
+
# Search for .torusguard
|
|
33
|
+
torusguard_dir = base / ".torusguard"
|
|
34
|
+
if not torusguard_dir.exists():
|
|
35
|
+
for parent in base.parents:
|
|
36
|
+
if (parent / ".torusguard").exists():
|
|
37
|
+
torusguard_dir = parent / ".torusguard"
|
|
38
|
+
break
|
|
39
|
+
|
|
40
|
+
patterns_file = torusguard_dir / "memory" / "patterns.json"
|
|
41
|
+
if not patterns_file.exists():
|
|
42
|
+
return 0
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
with open(patterns_file, "r", encoding="utf-8") as f:
|
|
46
|
+
patterns = json.load(f)
|
|
47
|
+
except Exception:
|
|
48
|
+
return 0
|
|
49
|
+
|
|
50
|
+
boost = 0
|
|
51
|
+
matched_file = False
|
|
52
|
+
|
|
53
|
+
for pat in patterns:
|
|
54
|
+
if pat.get("rule_id") == rule_id:
|
|
55
|
+
ptype = pat.get("pattern_type")
|
|
56
|
+
if ptype == "false_positive_class":
|
|
57
|
+
boost -= 30
|
|
58
|
+
elif ptype == "regression_watch":
|
|
59
|
+
boost += 15
|
|
60
|
+
elif ptype in ("recurring_fix", "common_vulnerability"):
|
|
61
|
+
boost += 10
|
|
62
|
+
elif ptype == "security_idiom":
|
|
63
|
+
boost += 5
|
|
64
|
+
|
|
65
|
+
# File-specific correlation bonus
|
|
66
|
+
if file_path and file_path in pat.get("affected_files", []):
|
|
67
|
+
matched_file = True
|
|
68
|
+
|
|
69
|
+
if matched_file and boost > 0:
|
|
70
|
+
boost += 5
|
|
71
|
+
elif matched_file and boost < 0:
|
|
72
|
+
boost -= 10
|
|
73
|
+
|
|
74
|
+
return boost
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def compute_confidence_score(
|
|
78
|
+
evidence_quality: int = 35,
|
|
79
|
+
reproduction_success: int = 0,
|
|
80
|
+
independent_confirmations: int = 5,
|
|
81
|
+
environmental_clarity: int = 15,
|
|
82
|
+
manual_review_status: int = 0,
|
|
83
|
+
memory_boost: int = 0,
|
|
84
|
+
rule_id: Optional[str] = None,
|
|
85
|
+
file_path: Optional[str] = None,
|
|
86
|
+
root_dir: Optional[Path] = None
|
|
87
|
+
) -> Tuple[int, str, Dict[str, int]]:
|
|
88
|
+
"""
|
|
89
|
+
Computes total score and assigns confidence band.
|
|
90
|
+
Max points:
|
|
91
|
+
- evidence_quality: 35
|
|
92
|
+
- reproduction_success: 25
|
|
93
|
+
- independent_confirmations: 15
|
|
94
|
+
- environmental_clarity: 15
|
|
95
|
+
- manual_review_status: 10
|
|
96
|
+
- memory_boost: -30 to +20 (modifier from persistent memory)
|
|
97
|
+
Total is clamped to [0, 100].
|
|
98
|
+
"""
|
|
99
|
+
eq = min(max(evidence_quality, 0), 35)
|
|
100
|
+
rs = min(max(reproduction_success, 0), 25)
|
|
101
|
+
ic = min(max(independent_confirmations, 0), 15)
|
|
102
|
+
ec = min(max(environmental_clarity, 0), 15)
|
|
103
|
+
mr = min(max(manual_review_status, 0), 10)
|
|
104
|
+
|
|
105
|
+
# Auto-calculate memory boost if rule_id provided and memory_boost == 0
|
|
106
|
+
eff_mem_boost = memory_boost
|
|
107
|
+
if rule_id and eff_mem_boost == 0:
|
|
108
|
+
eff_mem_boost = compute_memory_boost(rule_id, file_path=file_path, root_dir=root_dir)
|
|
109
|
+
|
|
110
|
+
raw_total = eq + rs + ic + ec + mr + eff_mem_boost
|
|
111
|
+
total = min(max(raw_total, 0), 100)
|
|
112
|
+
|
|
113
|
+
if total >= 90:
|
|
114
|
+
band = "Confirmed"
|
|
115
|
+
elif total >= 70:
|
|
116
|
+
band = "High Confidence"
|
|
117
|
+
elif total >= 50:
|
|
118
|
+
band = "Medium Confidence"
|
|
119
|
+
else:
|
|
120
|
+
band = "Needs Review"
|
|
121
|
+
|
|
122
|
+
factors = {
|
|
123
|
+
"evidence_quality": eq,
|
|
124
|
+
"reproduction_success": rs,
|
|
125
|
+
"independent_confirmations": ic,
|
|
126
|
+
"environmental_clarity": ec,
|
|
127
|
+
"manual_review_status": mr,
|
|
128
|
+
"memory_boost": eff_mem_boost,
|
|
129
|
+
"total_score": total,
|
|
130
|
+
"classification_band": band
|
|
131
|
+
}
|
|
132
|
+
return total, band, factors
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def main():
|
|
136
|
+
parser = argparse.ArgumentParser(description="TorusGuard Confidence Scorer")
|
|
137
|
+
parser.add_argument("--eq", type=int, default=35, help="Evidence quality score (0-35)")
|
|
138
|
+
parser.add_argument("--rs", type=int, default=0, help="Reproduction success score (0-25)")
|
|
139
|
+
parser.add_argument("--ic", type=int, default=5, help="Independent confirmations score (0-15)")
|
|
140
|
+
parser.add_argument("--ec", type=int, default=15, help="Environmental clarity score (0-15)")
|
|
141
|
+
parser.add_argument("--mr", type=int, default=0, help="Manual review status score (0-10)")
|
|
142
|
+
parser.add_argument("--memory-boost", type=int, default=0, help="Memory boost score (-30 to +20)")
|
|
143
|
+
parser.add_argument("--rule-id", type=str, help="TorusGuard rule ID for memory pattern matching")
|
|
144
|
+
parser.add_argument("--file", type=str, help="File path for correlation matching")
|
|
145
|
+
parser.add_argument("--json", action="store_true", help="Output JSON")
|
|
146
|
+
args = parser.parse_args()
|
|
147
|
+
|
|
148
|
+
total, band, factors = compute_confidence_score(
|
|
149
|
+
evidence_quality=args.eq,
|
|
150
|
+
reproduction_success=args.rs,
|
|
151
|
+
independent_confirmations=args.ic,
|
|
152
|
+
environmental_clarity=args.ec,
|
|
153
|
+
manual_review_status=args.mr,
|
|
154
|
+
memory_boost=args.memory_boost,
|
|
155
|
+
rule_id=args.rule_id,
|
|
156
|
+
file_path=args.file
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if args.json:
|
|
160
|
+
print(json.dumps(factors, indent=2))
|
|
161
|
+
else:
|
|
162
|
+
print(f"Total Confidence Score: {total}/100")
|
|
163
|
+
print(f"Classification Band: {band}")
|
|
164
|
+
print("Factor Breakdown:")
|
|
165
|
+
for k, v in factors.items():
|
|
166
|
+
if k not in ("total_score", "classification_band"):
|
|
167
|
+
print(f" - {k}: {v}")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
if __name__ == "__main__":
|
|
171
|
+
main()
|