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.
Files changed (44) hide show
  1. package/.torusguard/.manifest.json +15 -10
  2. package/.torusguard/config/torusguard.json +1 -1
  3. package/.torusguard/schemas/memory-context.schema.json +95 -0
  4. package/.torusguard/schemas/memory-event.schema.json +70 -0
  5. package/.torusguard/schemas/memory-pattern.schema.json +65 -0
  6. package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
  7. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  8. package/.torusguard/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  9. package/.torusguard/scripts/diff_guard.py +71 -11
  10. package/.torusguard/scripts/finding_scorer.py +171 -86
  11. package/.torusguard/scripts/manifest_builder.py +2 -0
  12. package/.torusguard/scripts/memory_engine.py +912 -0
  13. package/.torusguard/scripts/run_manager.py +171 -89
  14. package/.torusguard/skills/torusguard/SKILL.md +12 -7
  15. package/.torusguard/skills/torusguard/bootstrap.py +344 -56
  16. package/.torusguard/skills/torusguard-audit/SKILL.md +25 -25
  17. package/.torusguard/skills/torusguard-harden/SKILL.md +3 -3
  18. package/.torusguard/skills/torusguard-recheck/SKILL.md +3 -3
  19. package/.torusguard/workflows/memory.md +53 -0
  20. package/README.md +12 -2
  21. package/bin/torusguard.js +173 -43
  22. package/package.json +1 -1
  23. package/skills/torusguard/SKILL.md +4 -3
  24. package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
  25. package/skills/torusguard/bootstrap.py +244 -80
  26. package/skills/torusguard/payload/.manifest.json +15 -10
  27. package/skills/torusguard/payload/config/torusguard.json +1 -1
  28. package/skills/torusguard/payload/schemas/memory-context.schema.json +95 -0
  29. package/skills/torusguard/payload/schemas/memory-event.schema.json +70 -0
  30. package/skills/torusguard/payload/schemas/memory-pattern.schema.json +65 -0
  31. package/skills/torusguard/payload/scripts/diff_guard.py +71 -11
  32. package/skills/torusguard/payload/scripts/finding_scorer.py +171 -86
  33. package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
  34. package/skills/torusguard/payload/scripts/memory_engine.py +912 -0
  35. package/skills/torusguard/payload/scripts/run_manager.py +171 -89
  36. package/skills/torusguard/payload/skills/torusguard/SKILL.md +12 -7
  37. package/skills/torusguard/payload/skills/torusguard/bootstrap.py +344 -56
  38. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +25 -25
  39. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +3 -3
  40. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +3 -3
  41. package/skills/torusguard/payload/workflows/memory.md +53 -0
  42. package/skills/torusguard-audit/SKILL.md +25 -25
  43. package/skills/torusguard-harden/SKILL.md +3 -3
  44. package/skills/torusguard-recheck/SKILL.md +3 -3
@@ -10,7 +10,6 @@ import sys
10
10
  import shutil
11
11
  import json
12
12
  import argparse
13
- import subprocess
14
13
  from pathlib import Path
15
14
 
16
15
  # Ensure UTF-8 stdout/stderr on Windows consoles
@@ -25,6 +24,19 @@ if sys.stderr and hasattr(sys.stderr, "reconfigure"):
25
24
  except Exception:
26
25
  pass
27
26
 
27
+ # ─── ANSI Color Helpers ───────────────────────────────────────────────────────
28
+ BOLD = "\033[1m"
29
+ DIM = "\033[2m"
30
+ RESET = "\033[0m"
31
+ CYAN = "\033[36m"
32
+ GREEN = "\033[32m"
33
+ YELLOW = "\033[33m"
34
+ WHITE = "\033[97m"
35
+ GRAY = "\033[90m"
36
+ RED = "\033[31m"
37
+ BG_GREEN = "\033[42m"
38
+ BG_CYAN = "\033[46m"
39
+
28
40
 
29
41
  def find_project_root(start_dir=None):
30
42
  """Detect project root directory by searching for standard repo root markers."""
@@ -45,6 +57,114 @@ def find_project_root(start_dir=None):
45
57
  return current
46
58
 
47
59
 
60
+ def print_header():
61
+ """Print the branded TorusGuard header card."""
62
+ print(f"""
63
+ {CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}
64
+ {CYAN}│{RESET} {CYAN}│{RESET}
65
+ {CYAN}│{RESET} {BOLD}{WHITE}🛡️ T O R U S G U A R D{RESET} {GRAY}v0.9.5{RESET} {CYAN}│{RESET}
66
+ {CYAN}│{RESET} {DIM}Autonomous Security Engine for AI-Built Applications{RESET} {CYAN}│{RESET}
67
+ {CYAN}│{RESET} {CYAN}│{RESET}
68
+ {CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}
69
+ """)
70
+
71
+
72
+ def print_step_1_assets(file_count):
73
+ """Print the enhanced Step 1 asset unpacking card."""
74
+ print(f""" {CYAN}┌─ {BOLD}Step 1/3{RESET} {CYAN}──────────────────────── {WHITE}Unpacking Governance Assets{RESET} {CYAN}──────┐{RESET}
75
+ {CYAN}│{RESET} {CYAN}│{RESET}
76
+ {CYAN}│{RESET} {GREEN}✔{RESET} Canonical security rules {DIM}71 rules across 11 families{RESET} {CYAN}│{RESET}
77
+ {CYAN}│{RESET} {GREEN}✔{RESET} JSON validation schemas {DIM}8 formal schemas{RESET} {CYAN}│{RESET}
78
+ {CYAN}│{RESET} {GREEN}✔{RESET} Specialist agent specifications {DIM}5 isolated agents{RESET} {CYAN}│{RESET}
79
+ {CYAN}│{RESET} {GREEN}✔{RESET} Workflow templates {DIM}11 slash commands{RESET} {CYAN}│{RESET}
80
+ {CYAN}│{RESET} {GREEN}✔{RESET} Framework reference guides {DIM}10 security guides{RESET} {CYAN}│{RESET}
81
+ {CYAN}│{RESET} {CYAN}│{RESET}
82
+ {CYAN}│{RESET} {BOLD}{WHITE}{file_count} files unpacked{RESET} {CYAN}│{RESET}
83
+ {CYAN}└───────────────────────────────────────────────────────────────────────┘{RESET}
84
+ """)
85
+
86
+
87
+ def print_step_2_profile(detected_stack=None):
88
+ """Print the security profile & coverage card (in-process stack alignment)."""
89
+ if detected_stack and detected_stack.get("framework") and detected_stack.get("framework") != "None":
90
+ fw = str(detected_stack.get("framework"))
91
+ lang = str(detected_stack.get("language", ""))
92
+ label = f"Auto-aligned stack: {fw} ({lang})"
93
+ pad = " " * max(0, 66 - len(label))
94
+ status_line = f" {CYAN}│{RESET} {GREEN}✔{RESET} {BOLD}Auto-aligned stack:{RESET} {WHITE}{fw}{RESET} {DIM}({lang}){RESET}{pad}{CYAN}│{RESET}"
95
+ else:
96
+ status_line = f" {CYAN}│{RESET} {DIM}ℹ Stack auto-detected on first /torusguard-audit run{RESET} {CYAN}│{RESET}"
97
+
98
+ print(f""" {CYAN}┌─ {BOLD}Step 2/3{RESET} {CYAN}──────────────────── {WHITE}Security Profile & Coverage{RESET} {CYAN}────────┐{RESET}
99
+ {CYAN}│{RESET} {CYAN}│{RESET}
100
+ {CYAN}│{RESET} {BOLD}Rule Families:{RESET} {CYAN}│{RESET}
101
+ {CYAN}│{RESET} {YELLOW}TG-SEC{RESET} Secrets & Credentials {YELLOW}TG-DB{RESET} Database Safety {CYAN}│{RESET}
102
+ {CYAN}│{RESET} {YELLOW}TG-INPUT{RESET} Input Validation {YELLOW}TG-AUTH{RESET} Authentication {CYAN}│{RESET}
103
+ {CYAN}│{RESET} {YELLOW}TG-CLIENT{RESET} Client Bundle Leaks {YELLOW}TG-DIFF{RESET} Diff Inspection {CYAN}│{RESET}
104
+ {CYAN}│{RESET} {YELLOW}TG-AGENT{RESET} AI Agent Security {YELLOW}TG-EDGE{RESET} Serverless {CYAN}│{RESET}
105
+ {CYAN}│{RESET} {YELLOW}TG-SUPPLY{RESET} Supply Chain & CI/CD {YELLOW}TG-SSRF{RESET} Outbound Net {CYAN}│{RESET}
106
+ {CYAN}│{RESET} {YELLOW}TG-BIZ{RESET} Business Logic {CYAN}│{RESET}
107
+ {CYAN}│{RESET} {CYAN}│{RESET}
108
+ {CYAN}│{RESET} {BOLD}Supported Stacks:{RESET} {CYAN}│{RESET}
109
+ {CYAN}│{RESET} {GREEN}Python{RESET} Django {DIM}·{RESET} FastAPI {DIM}·{RESET} Flask {DIM}·{RESET} DRF {DIM}·{RESET} SQLAlchemy {CYAN}│{RESET}
110
+ {CYAN}│{RESET} {GREEN}Node.js{RESET} Next.js {DIM}·{RESET} Express {DIM}·{RESET} React {DIM}·{RESET} Supabase {DIM}·{RESET} Firebase {CYAN}│{RESET}
111
+ {CYAN}│{RESET} {CYAN}│{RESET}
112
+ {status_line}
113
+ {CYAN}└───────────────────────────────────────────────────────────────────────┘{RESET}
114
+ """)
115
+
116
+
117
+ def print_step_3_bridges(registered_ides):
118
+ """Print the IDE command registration card."""
119
+ lines = ""
120
+ for r in registered_ides:
121
+ lines += f" {CYAN}│{RESET} {GREEN}✔{RESET} {r:<67} {CYAN}│{RESET}\n"
122
+
123
+ print(f""" {CYAN}┌─ {BOLD}Step 3/3{RESET} {CYAN}─────────────────── {WHITE}AI IDE Command Registration{RESET} {CYAN}─────────┐{RESET}
124
+ {CYAN}│{RESET} {CYAN}│{RESET}
125
+ {lines} {CYAN}│{RESET} {CYAN}│{RESET}
126
+ {CYAN}└───────────────────────────────────────────────────────────────────────┘{RESET}
127
+ """)
128
+
129
+
130
+ def print_success_card():
131
+ """Print the final success card with next steps."""
132
+ print(f""" {GREEN}╔═══════════════════════════════════════════════════════════════════════╗{RESET}
133
+ {GREEN}║{RESET} {GREEN}║{RESET}
134
+ {GREEN}║{RESET} {GREEN}{BOLD}✅ WORKSPACE INITIALIZED SUCCESSFULLY{RESET} {GREEN}║{RESET}
135
+ {GREEN}║{RESET} {GREEN}║{RESET}
136
+ {GREEN}╠═══════════════════════════════════════════════════════════════════════╣{RESET}
137
+ {GREEN}║{RESET} {GREEN}║{RESET}
138
+ {GREEN}║{RESET} {BOLD}Next Steps:{RESET} {GREEN}║{RESET}
139
+ {GREEN}║{RESET} {GREEN}║{RESET}
140
+ {GREEN}║{RESET} {CYAN}1.{RESET} In AI Chat {WHITE}/torusguard-audit{RESET} or {WHITE}/torusguard{RESET} {GREEN}║{RESET}
141
+ {GREEN}║{RESET} {CYAN}2.{RESET} In Terminal {WHITE}npx torusguard status{RESET} {GREEN}║{RESET}
142
+ {GREEN}║{RESET} {CYAN}3.{RESET} In CI/CD {WHITE}npx torusguard audit{RESET} {GREEN}║{RESET}
143
+ {GREEN}║{RESET} {GREEN}║{RESET}
144
+ {GREEN}║{RESET} {DIM}Docs{RESET} {CYAN}https://github.com/githubmofo/TorusGuard{RESET} {GREEN}║{RESET}
145
+ {GREEN}║{RESET} {DIM}NPM{RESET} {CYAN}https://npmjs.com/package/torusguard{RESET} {GREEN}║{RESET}
146
+ {GREEN}║{RESET} {GREEN}║{RESET}
147
+ {GREEN}╚═══════════════════════════════════════════════════════════════════════╝{RESET}
148
+ """)
149
+
150
+
151
+ def print_already_initialized(target_root, cfg):
152
+ """Print the already-initialized status card."""
153
+ print(f"""
154
+ {CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}
155
+ {CYAN}│{RESET} {BOLD}{WHITE}🛡️ TORUSGUARD WORKSPACE{RESET} {GREEN}[Active]{RESET} {CYAN}│{RESET}
156
+ {CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}
157
+
158
+ {BOLD}▸ Project Root:{RESET} {GREEN}{target_root}{RESET}
159
+ {BOLD}▸ Workspace:{RESET} {GREEN}.torusguard/{RESET} {DIM}(Already Initialized){RESET}
160
+ {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '1.0.0')}{RESET}
161
+ {BOLD}▸ Severity Floor:{RESET} {YELLOW}{cfg.get('severity_threshold', 'medium')}{RESET}
162
+
163
+ {DIM}To refresh templates or re-scaffold, run:{RESET}
164
+ {CYAN}npx torusguard init --force{RESET}
165
+ """)
166
+
167
+
48
168
  def scaffold_workspace(target_root=None, force=False, full_commands=False):
49
169
  """Scaffold the .torusguard workspace into the target project root."""
50
170
  target_root = Path(target_root or find_project_root()).resolve()
@@ -53,40 +173,25 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
53
173
  payload_dir = script_dir / "payload"
54
174
 
55
175
  if torusguard_target.exists() and not force:
56
- print("""
57
- ╭──────────────────────────────────────────────────────────────────────────╮
58
- │ 🛡️ TORUSGUARD WORKSPACE STATUS [Active] │
59
- ╰──────────────────────────────────────────────────────────────────────────╯
60
- """)
61
- print(f" ▸ Project Root: {target_root}")
62
- print(f" ▸ Workspace: .torusguard/ (Already Initialized)")
63
176
  config_file = torusguard_target / "config" / "torusguard.json"
177
+ cfg = {}
64
178
  if config_file.exists():
65
179
  try:
66
180
  with open(config_file, "r", encoding="utf-8") as f:
67
181
  cfg = json.load(f)
68
- print(f" ▸ Version: {cfg.get('version', '0.9.3')}")
69
- print(f" ▸ Severity Floor: {cfg.get('severity_threshold', 'medium')}")
70
182
  except Exception:
71
183
  pass
72
- print("""
73
- 💡 Workspace already exists. To refresh templates or re-scaffold, run:
74
- npx torusguard init --force
75
- """)
184
+ print_already_initialized(target_root, cfg)
76
185
  return True
77
186
 
78
- print("""
79
- ╭──────────────────────────────────────────────────────────────────────────╮
80
- │ 🛡️ TORUSGUARD WORKSPACE INITIALIZATION v0.9.3 │
81
- │ Governed Remediation & AI Application Guardrails │
82
- ╰──────────────────────────────────────────────────────────────────────────╯
83
- """)
84
- print(f" ▸ Target Project: {target_root}")
85
- print(f" ▸ Destination: {torusguard_target}")
187
+ # ── Header ──────────────────────────────────────────────────────────────
188
+ print_header()
189
+ print(f" {BOLD}▸ Target Project:{RESET} {WHITE}{target_root}{RESET}")
190
+ print(f" {BOLD}▸ Destination:{RESET} {WHITE}{torusguard_target}{RESET}")
86
191
 
87
- # 1. Unpack Payload Template
192
+ # ── Step 1: Unpack Payload ──────────────────────────────────────────────
193
+ file_count = 93
88
194
  if payload_dir.is_dir():
89
- print("\n ▸ Step 1/3: Unpacking Offline Governance Assets...")
90
195
  try:
91
196
  if torusguard_target.exists() and force:
92
197
  shutil.rmtree(torusguard_target)
@@ -95,22 +200,25 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
95
200
  torusguard_target,
96
201
  ignore=shutil.ignore_patterns("runs", "*.pyc", "__pycache__", ".git*")
97
202
  )
98
- print(" ✔ Copied canonical rules, schemas, scripts, and workflows (93 files)")
203
+ # Count actual files
204
+ file_count = sum(1 for _ in torusguard_target.rglob("*") if _.is_file())
99
205
  except Exception as e:
100
- print(f" ❌ Failed to unpack payload: {e}")
206
+ print(f"\n {RED}✖ Failed to unpack payload: {e}{RESET}")
101
207
  return False
102
208
  else:
103
209
  # Fallback: create base structure
104
- print("\n1. Bundled payload not found. Creating core skeleton...")
105
210
  subdirs = [
106
211
  "config", "agents", "workflows", "scripts", "templates",
107
212
  "schemas", "references", "rules/active", "runs"
108
213
  ]
109
214
  for s in subdirs:
110
215
  (torusguard_target / s).mkdir(parents=True, exist_ok=True)
111
- print(" [WARN] Bare skeleton created; full assets should be pulled from repository.")
216
+ file_count = 0
112
217
 
113
- # 2. Ensure runs and rules/active directories exist
218
+ print()
219
+ print_step_1_assets(file_count)
220
+
221
+ # ── Ensure runs and rules/active directories exist ──────────────────────
114
222
  runs_dir = torusguard_target / "runs"
115
223
  runs_dir.mkdir(parents=True, exist_ok=True)
116
224
  gitkeep_runs = runs_dir / ".gitkeep"
@@ -123,50 +231,115 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
123
231
  if not gitkeep_rules.exists():
124
232
  gitkeep_rules.write_text("", encoding="utf-8")
125
233
 
126
- # 3. Stack Detection & Tailoring
127
- print("\n ▸ Step 2/3: Executing Stack Detection & Rule Alignment...")
234
+ # ── Ensure memory subsystem is initialized (v1.0.0) ────────────────────
235
+ memory_dir = torusguard_target / "memory"
236
+ memory_dir.mkdir(parents=True, exist_ok=True)
237
+ events_dir = memory_dir / "events"
238
+ events_dir.mkdir(parents=True, exist_ok=True)
239
+
240
+ gitkeep_events = events_dir / ".gitkeep"
241
+ if not gitkeep_events.exists():
242
+ gitkeep_events.write_text("", encoding="utf-8")
243
+
244
+ mem_gitignore = memory_dir / ".gitignore"
245
+ if not mem_gitignore.exists():
246
+ mem_gitignore.write_text("*\n", encoding="utf-8")
247
+
248
+ decay_file = memory_dir / "decay.json"
249
+ if not decay_file.exists():
250
+ decay_file.write_text(json.dumps({
251
+ "default_ttl_days": 90,
252
+ "decay_rate": 0.15,
253
+ "last_decay_run": None
254
+ }, indent=2), encoding="utf-8")
255
+
256
+ patterns_file = memory_dir / "patterns.json"
257
+ if not patterns_file.exists():
258
+ patterns_file.write_text("[]", encoding="utf-8")
259
+
260
+ profile_file = memory_dir / "profile.json"
261
+ if not profile_file.exists():
262
+ profile_file.write_text(json.dumps({
263
+ "stack": [],
264
+ "total_events": 0,
265
+ "active_patterns_count": 0,
266
+ "fix_rate_percentage": None,
267
+ "top_vulnerabilities": [],
268
+ "last_updated": None
269
+ }, indent=2), encoding="utf-8")
270
+
271
+ context_file = memory_dir / "context.json"
272
+ if not context_file.exists():
273
+ context_file.write_text(json.dumps({
274
+ "version": "1.0.0",
275
+ "generated_at": None,
276
+ "token_estimate": 0,
277
+ "max_token_budget": 2000,
278
+ "project_profile": {
279
+ "stack": [],
280
+ "total_events": 0,
281
+ "active_patterns_count": 0,
282
+ "fix_rate_percentage": None,
283
+ "top_vulnerabilities": []
284
+ },
285
+ "cards": []
286
+ }, indent=2), encoding="utf-8")
287
+
288
+ # Ensure target project root .gitignore excludes .torusguard/memory/
289
+ root_gitignore = target_root / ".gitignore"
290
+ if root_gitignore.exists():
291
+ try:
292
+ gi_content = root_gitignore.read_text(encoding="utf-8")
293
+ if ".torusguard/memory" not in gi_content:
294
+ root_gitignore.write_text(gi_content.rstrip() + "\n\n# TorusGuard security memory (local only)\n.torusguard/memory/\n", encoding="utf-8")
295
+ except Exception:
296
+ pass
297
+
298
+ # ── Step 2: Security Profile & Coverage (In-Process, Zero Subprocess) ──
299
+ # Execute stack detection in-process without spawning child processes (Socket.dev safe)
300
+ detected_stack = None
128
301
  stack_detect_script = torusguard_target / "scripts" / "stack_detect.py"
129
- detected_stack = {"language": "Unknown", "framework": "None", "data_layer": "None", "confidence": "Uncertain"}
130
-
131
- if stack_detect_script.exists():
302
+ if stack_detect_script.is_file():
132
303
  try:
133
- res = subprocess.run(
134
- [sys.executable, str(stack_detect_script), str(target_root), "--json"],
135
- capture_output=True,
136
- text=True,
137
- timeout=10
138
- )
139
- if res.returncode == 0 and res.stdout.strip():
140
- detected_stack = json.loads(res.stdout)
141
- print(f" ⎿ Language: {detected_stack.get('language')}")
142
- print(f" ⎿ Framework: {detected_stack.get('framework')}")
143
- print(f" ⎿ Data Layer: {detected_stack.get('data_layer')}")
144
- except Exception as e:
145
- print(f" ⚠ Stack detection warning: {e}")
304
+ import importlib.util
305
+ spec = importlib.util.spec_from_file_location("stack_detect", str(stack_detect_script))
306
+ if spec and spec.loader:
307
+ sd_mod = importlib.util.module_from_spec(spec)
308
+ spec.loader.exec_module(sd_mod)
309
+ if hasattr(sd_mod, "detect_stack"):
310
+ detected_stack = sd_mod.detect_stack(target_root)
311
+ except Exception:
312
+ detected_stack = None
146
313
 
147
- # 4. Update torusguard.json configuration
148
314
  config_file = torusguard_target / "config" / "torusguard.json"
149
315
  if config_file.exists():
150
316
  try:
151
317
  with open(config_file, "r", encoding="utf-8") as f:
152
318
  cfg = json.load(f)
153
- cfg["detected_stack"] = {
154
- "language": detected_stack.get("language"),
155
- "framework": detected_stack.get("framework"),
156
- "data_layer": detected_stack.get("data_layer")
157
- }
319
+ if detected_stack and detected_stack.get("framework") != "None":
320
+ cfg["detected_stack"] = {
321
+ "language": detected_stack.get("language"),
322
+ "framework": detected_stack.get("framework"),
323
+ "data_layer": detected_stack.get("data_layer")
324
+ }
325
+ else:
326
+ cfg["detected_stack"] = {
327
+ "language": "Unknown",
328
+ "framework": "None",
329
+ "data_layer": "None"
330
+ }
158
331
  with open(config_file, "w", encoding="utf-8") as f:
159
332
  json.dump(cfg, f, indent=2)
160
- print(" ✔ Configured .torusguard/config/torusguard.json (71 Rules Active)")
161
- except Exception as e:
162
- print(f" ⚠ Config update error: {e}")
333
+ except Exception:
334
+ pass
335
+
336
+ print_step_2_profile(detected_stack)
163
337
 
164
- # 5. Register Slash Commands for AI IDEs (.agent, .claude, .cursor)
165
- print("\n ▸ Step 3/3: Registering AI IDE Command Bridges...")
338
+ # ── Step 3: Register Slash Commands for AI IDEs ─────────────────────────
166
339
  registered_ides = []
167
340
  tg_workflow_content = """---
168
341
  description: TorusGuard Autonomous Security Command Engine — run static security audits, authorized runtime web validation, governed remediation, and SARIF exports.
169
- version: 0.9.2
342
+ version: 1.0.0
170
343
  tools: Read, Grep, Glob, Bash, Edit, Write
171
344
  agent: auditor
172
345
  ---
@@ -192,16 +365,16 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
192
365
  agents_wf.mkdir(parents=True, exist_ok=True)
193
366
  (agents_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
194
367
  dest_workflow_dirs.append(agents_wf)
195
- registered_ides.append("Antigravity / Gemini (.agents/workflows/torusguard.md)")
368
+ registered_ides.append("Antigravity / Gemini .agents/workflows/torusguard.md")
196
369
 
197
370
  agent_wf = target_root / ".agent" / "workflows"
198
371
  agent_wf.mkdir(parents=True, exist_ok=True)
199
372
  (agent_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
200
373
  dest_workflow_dirs.append(agent_wf)
201
- registered_ides.append("Antigravity / Tribunal (.agent/workflows/torusguard.md)")
374
+ registered_ides.append("Tribunal Agent Kit .agent/workflows/torusguard.md")
202
375
 
203
376
  # When full_commands is requested (e.g. via NPM package npx torusguard init),
204
- # unlock and register all 11 individual slash commands (/torusguard-audit, /torusguard-harden, etc.)
377
+ # unlock and register all 11 individual slash commands
205
378
  if full_commands:
206
379
  src_wf = torusguard_target / "workflows"
207
380
  if src_wf.is_dir():
@@ -213,7 +386,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
213
386
  for d in dest_workflow_dirs:
214
387
  shutil.copy2(wf_file, d / cmd_filename)
215
388
  count += 1
216
- registered_ides.append(f"Unlocked {count} Individual Slash Commands (/torusguard-audit, /torusguard-apply, etc.)")
389
+ registered_ides.append(f"{count} Slash Commands /torusguard-audit, -harden, -apply, ...")
217
390
 
218
391
  # Claude Code (.claude/commands)
219
392
  claude_dir = target_root / ".claude"
@@ -221,7 +394,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
221
394
  claude_commands = claude_dir / "commands"
222
395
  claude_commands.mkdir(parents=True, exist_ok=True)
223
396
  (claude_commands / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
224
- registered_ides.append("Claude Code (.claude/commands/torusguard.md)")
397
+ registered_ides.append("Claude Code .claude/commands/torusguard.md")
225
398
 
226
399
  # Cursor (.cursor/rules)
227
400
  cursor_dir = target_root / ".cursor"
@@ -229,7 +402,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
229
402
  cursor_rules = cursor_dir / "rules"
230
403
  cursor_rules.mkdir(parents=True, exist_ok=True)
231
404
  (cursor_rules / "torusguard.mdc").write_text(tg_workflow_content, encoding="utf-8")
232
- registered_ides.append("Cursor (.cursor/rules/torusguard.mdc)")
405
+ registered_ides.append("Cursor .cursor/rules/torusguard.mdc")
233
406
 
234
407
  # Windsurf (.windsurfrules)
235
408
  if (target_root / ".windsurfrules").exists() or (target_root / ".windsurf").exists():
@@ -237,7 +410,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
237
410
  current_content = windsurf_rules.read_text(encoding="utf-8") if windsurf_rules.exists() else ""
238
411
  if "TorusGuard" not in current_content:
239
412
  windsurf_rules.write_text(current_content + "\n\n" + tg_workflow_content, encoding="utf-8")
240
- registered_ides.append("Windsurf (.windsurfrules)")
413
+ registered_ides.append("Windsurf .windsurfrules")
241
414
 
242
415
  # VS Code / GitHub Copilot (.github/copilot-instructions.md)
243
416
  github_dir = target_root / ".github"
@@ -246,28 +419,19 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
246
419
  current_content = copilot_file.read_text(encoding="utf-8") if copilot_file.exists() else ""
247
420
  if "TorusGuard" not in current_content:
248
421
  copilot_file.write_text(current_content + "\n\n# TorusGuard Security Instructions\n" + tg_workflow_content, encoding="utf-8")
249
- registered_ides.append("VS Code / Copilot (.github/copilot-instructions.md)")
422
+ registered_ides.append("VS Code / Copilot .github/copilot-instructions.md")
250
423
 
251
424
  # Universal AGENTS.md (Kimi, Codex, Open Agent Standard)
252
425
  agents_md = target_root / "AGENTS.md"
253
426
  current_agents = agents_md.read_text(encoding="utf-8") if agents_md.exists() else ""
254
427
  if "TorusGuard" not in current_agents:
255
428
  agents_md.write_text(current_agents + ("\n\n" if current_agents else "") + "# TorusGuard Security Guardrails\n\nRun `/torusguard audit` to scan the codebase or refer to `.torusguard/` for security guidelines.\n", encoding="utf-8")
256
- registered_ides.append("Universal Agent Standard (AGENTS.md for Kimi / Open Agents)")
429
+ registered_ides.append("Universal AGENTS.md Kimi / Open Agent Standard")
257
430
 
258
- for r in registered_ides:
259
- print(f" ✔ {r}")
431
+ print_step_3_bridges(registered_ides)
260
432
 
261
- print(f"""
262
- ╭──────────────────────────────────────────────────────────────────────────╮
263
- │ ✨ TorusGuard Workspace Initialized Successfully! │
264
- │ │
265
- │ 🚀 Next Steps: │
266
- │ 1. In AI Chat: Type `/torusguard-audit` or `/torusguard` to scan │
267
- │ 2. In Terminal: Run `npx torusguard status` for security posture │
268
- │ 3. In CI/CD: Run `npx torusguard audit` to generate SARIF data │
269
- ╰──────────────────────────────────────────────────────────────────────────╯
270
- """)
433
+ # ── Success Card ────────────────────────────────────────────────────────
434
+ print_success_card()
271
435
  return True
272
436
 
273
437
 
@@ -8,7 +8,7 @@
8
8
  "agents/validator.md": "79fc4431de5c5507f8730aee6c5c3e61fd238cbf8cf8c7c6aac462eee9761ed6",
9
9
  "config/scope.json": "b198a86186b4c6d5e1af516bf4e3a6afa8878e622ca1d57a5bf72d294f8c6f25",
10
10
  "config/slash-commands.json": "5390f0d26f8117a62e56c58147d3a0d2deab1a20956302b212703281d13fa84e",
11
- "config/torusguard.json": "218eeae10b538aca9b548d1b756d7d4f91a5b624e0bce07533f0c187860586e6",
11
+ "config/torusguard.json": "b979d6ead31e64a63729e050d820f3e3228d3c825972a60ccae2087e6b27f574",
12
12
  "references/django-security.md": "a15b7eb11b51dd1970d3d65544cf79ebea91fb99dc0e085e58a56532a718dce7",
13
13
  "references/drf-security.md": "c7a7af3acaef895bf4798590acc88b3a2e9831a49eb2d23b4d8f31540ab264cc",
14
14
  "references/express-security.md": "dff1db15e614d29d8c272f9da345b418077e62dc883fe210c7a50c552c76493f",
@@ -28,20 +28,24 @@
28
28
  "schemas/confidence.schema.json": "08b3a564d7370e123dd5bfadde9fb077d2954e36b523685b9e1d7bdd2aa4b8cb",
29
29
  "schemas/evidence.schema.json": "d3dcaa10fd2420a4046ea68836fb836a55d003ada4cdc6682229f232881182bf",
30
30
  "schemas/finding.schema.json": "e0a7c28fa4a5f84bdedb5cf5223da26348250d633479d2dbf7ce3ebd6790a852",
31
+ "schemas/memory-context.schema.json": "6b9e032c55ba87b2517dd1e7ca0043b8e2439e85fa4a6eac6fc6041f3091e571",
32
+ "schemas/memory-event.schema.json": "4f653610e04fd480325d0ec77a4339bea4690f85e1d2fa0bd4f6b654c813c905",
33
+ "schemas/memory-pattern.schema.json": "df4aae2a3034a7c64ec50b3ae27b6ee9296aac7371c2a1938508834e5f778afe",
31
34
  "schemas/provenance.schema.json": "781215801249532414643638b6608dc8f52febc9bca43ae03827b90aecc03256",
32
35
  "schemas/remediation.schema.json": "217cb2743ae1a912dc074382e9f05634da93f2e30a880c03f6020600ef7e43d3",
33
36
  "schemas/retest.schema.json": "773b764082f6d2e8c3656ea105e0ce09febd1020520bf262bbcd17f5924da11e",
34
37
  "schemas/runtime-evidence.schema.json": "dbe13741a7fb68cca2a044d47a644ee0bdaacb83a28621dc2a98bffdd59989a6",
35
- "scripts/diff_guard.py": "227bf56d2e6c9aef293a51ad1a3209782e6d9204dc1775956d372c3a6851a736",
36
- "scripts/finding_scorer.py": "b78c6315f22000fb64f5d4e6ff1f3467439769d3d5507aaa99380453df4eb464",
37
- "scripts/manifest_builder.py": "b759131592966053db17ef710dc5f313127a9583295cb867a39ab22a7c996580",
38
+ "scripts/diff_guard.py": "5937b657c1047c78b7b9f0a36f3438cb699457cdb5ee56136d68b97edf56af42",
39
+ "scripts/finding_scorer.py": "c9f34c9153f5322c92bba824ce199ea281c450cd8edc637e61442c5f556d6183",
40
+ "scripts/manifest_builder.py": "136d5650a97dbb52fdf42c6d55b330a4f9593816e344b07913b0b2ba6b5cc409",
41
+ "scripts/memory_engine.py": "e99d34951b953bf3d96b6fca2413192de76778e6519278d4213fa3a72bc9b05f",
38
42
  "scripts/monorepo_detector.py": "38f1eb948ee2856f175e1212956bce211effdd1327d3a31f7303d32ba9478ebe",
39
- "scripts/run_manager.py": "e853874e4fb0cb697596ea338f71ba7e955f2b41a6fc649733b45fa755e94768",
43
+ "scripts/run_manager.py": "b576fc3be9929ee6a52e67662e67f801e4e9317c158243582911e10c94a07619",
40
44
  "scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
41
45
  "scripts/sarif_exporter.py": "35c66637413afc4b72d5bd426638447c77231d2a8594dce5addceffd4803a20d",
42
46
  "scripts/stack_detect.py": "99b7bdf9829d58ff5b8c59afd6e8b6429bbb11d830ac73dec491101cbbc41574",
43
- "skills/torusguard/SKILL.md": "5282a9e73c2faad97f079ff527def34b96709615c0dd297fe9b1bb2894f03e20",
44
- "skills/torusguard/bootstrap.py": "7e348065a622089ab1d51e9bf4864e5b0022aaee1ccb2ecbf7057c14e792e2c7",
47
+ "skills/torusguard/SKILL.md": "e772e348716aee26e424ec96be5bd6750dbebcefc248bc4dab0df1e6c0e24fcf",
48
+ "skills/torusguard/bootstrap.py": "7c5a13687578a8736aef25cf767d1ef3c8b82dcae0eb7efce41bf131d27a120f",
45
49
  "skills/torusguard/references/auth-and-sessions.md": "34c2843f8c0dbe3574e54f00a39a92a1f431527ec5f69b2d64c84240d424a39e",
46
50
  "skills/torusguard/references/business-logic-and-abuse.md": "0d6088936bc1a01023070332fccef0f2e0734358a5119379055f3d2895c22567",
47
51
  "skills/torusguard/references/cache-and-sensitive-responses.md": "8f920cacde29c50b1f5f98de341a60db0bc607fe8c212a7e618ef7af08c86511",
@@ -66,13 +70,13 @@
66
70
  "skills/torusguard/references/webhook-security.md": "a0c7efb663c664dd840ba99b689cb67d4688643106f8b6e80d18a424c6add386",
67
71
  "skills/torusguard/references/websocket-security.md": "5624a84abd75bbb4eed029cd217e0c794ee452cbecc0730a8ab4d0f371537cd7",
68
72
  "skills/torusguard-apply/SKILL.md": "9436fa5cdefa661677ada22936a3949de06aca276e4f4bb27e0ef5b7ea34edc3",
69
- "skills/torusguard-audit/SKILL.md": "d0e0c21d6c36d9d128ccce6ad628b978ff771d27552ba80e0a4981e18b9f5a51",
73
+ "skills/torusguard-audit/SKILL.md": "f879e280d357ea7f124c647ce39af2b24b79db608c9edd018f26e5312625a8b5",
70
74
  "skills/torusguard-authorize/SKILL.md": "da849585f2e46c08ef528b89737be14647f1109fd365fd27f3f6da57a396724b",
71
75
  "skills/torusguard-exploit-check/SKILL.md": "e9a173e154a88cc9cb929c59d79a65ab13d5cf9567b4112bd7f272746cf9c3f9",
72
76
  "skills/torusguard-full/SKILL.md": "cc97684d37de378e51fefd12f6f9a7cd15cc469ce46079a0599440aa7b073f7b",
73
- "skills/torusguard-harden/SKILL.md": "86a8dee6c614477e2122287752f5c16e3688c0451d0e7ae9bfd2a23802bcdde3",
77
+ "skills/torusguard-harden/SKILL.md": "326fa84bda4832f96b19d73824c3472dfe185247ed3e3db9715dd943d46d9874",
74
78
  "skills/torusguard-init/SKILL.md": "1f7844d66219955581fdb266029eefdc355dbebb5741b848daf0062e606202a2",
75
- "skills/torusguard-recheck/SKILL.md": "4725a9be6a6ddedb3d389d1957c7ce3e0f9ce288107816fce85b5953951e13e5",
79
+ "skills/torusguard-recheck/SKILL.md": "457b2a1cce064a738fbe43f0dba6b4393f1630a82f60698ea5ebe655ec017e50",
76
80
  "skills/torusguard-report/SKILL.md": "bde44d114bdc85c04472644a644a7796ed2f182a23e0c057838a3251e4910a09",
77
81
  "skills/torusguard-status/SKILL.md": "4e71d03c71b240afd7f6108569530b7da3702634c512a74ca8dc3174f3c6b0fb",
78
82
  "skills/torusguard-verify/SKILL.md": "10c19e0926255686351e3b75ae774880cf35562d42bd30b87a877bb8f284fc1f",
@@ -87,6 +91,7 @@
87
91
  "workflows/exploit-check.md": "9684009b835a61d5aca8827a971ee686a24c800425d86ef96f963dd27de845b8",
88
92
  "workflows/harden.md": "509484f844c9dcd10dd14c8bb6e3456021928e6cf6abd374faaf34be8fc34ce2",
89
93
  "workflows/init.md": "3d1668a9f6b87417c31f47c887c495f863595ed4a29074e0c5a8ee1ece1d4a35",
94
+ "workflows/memory.md": "c034f9266380db3c05e9ffed943c2bb4ba73c060507e3508e47b543a035a5873",
90
95
  "workflows/recheck.md": "7d374c29a5585c31b81f84fb32d6a466f2e9cb339726dc0523dba25e57bc5d13",
91
96
  "workflows/report.md": "56b3449cff362172c63093ee6150446d11bf05e3c8143661966dad9d42df1470",
92
97
  "workflows/status.md": "921129646518c592cb47ad8e8ccf3d703e8d11ea6eb89bd21a206f545e022dba",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "../schemas/torusguard-config.schema.json",
3
- "version": "0.9.4",
3
+ "version": "1.0.0",
4
4
  "product": "TorusGuard Security Skill Kit",
5
5
  "severity_threshold": "medium",
6
6
  "auto_detect_stack": true,
@@ -0,0 +1,95 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "torusguard-memory-context.schema.json",
4
+ "title": "TorusGuard Memory Context Window",
5
+ "description": "Pre-computed, token-budgeted context window for AI agent consumption formatted as structured JSON cards.",
6
+ "type": "object",
7
+ "required": ["version", "generated_at", "token_estimate", "max_token_budget", "project_profile", "cards"],
8
+ "properties": {
9
+ "version": {
10
+ "type": "string",
11
+ "description": "TorusGuard engine version (e.g., 1.0.0)."
12
+ },
13
+ "generated_at": {
14
+ "type": "string",
15
+ "format": "date-time",
16
+ "description": "ISO 8601 UTC timestamp when this context window was computed."
17
+ },
18
+ "token_estimate": {
19
+ "type": "integer",
20
+ "minimum": 0,
21
+ "description": "Estimated token count of this context document."
22
+ },
23
+ "max_token_budget": {
24
+ "type": "integer",
25
+ "default": 2000,
26
+ "description": "Maximum allowed tokens for agent context injection (default: 2000)."
27
+ },
28
+ "project_profile": {
29
+ "type": "object",
30
+ "required": ["stack", "total_events", "active_patterns_count"],
31
+ "properties": {
32
+ "stack": {
33
+ "type": "array",
34
+ "items": { "type": "string" },
35
+ "description": "Detected technology stack frameworks/languages."
36
+ },
37
+ "total_events": {
38
+ "type": "integer",
39
+ "minimum": 0
40
+ },
41
+ "active_patterns_count": {
42
+ "type": "integer",
43
+ "minimum": 0
44
+ },
45
+ "fix_rate_percentage": {
46
+ "type": ["number", "null"],
47
+ "minimum": 0,
48
+ "maximum": 100
49
+ },
50
+ "top_vulnerabilities": {
51
+ "type": "array",
52
+ "items": { "type": "string" }
53
+ }
54
+ }
55
+ },
56
+ "cards": {
57
+ "type": "array",
58
+ "description": "Ordered list of high-priority intelligence cards for LLM grounding.",
59
+ "items": {
60
+ "type": "object",
61
+ "required": ["card_id", "card_type", "priority", "title", "summary", "card_data"],
62
+ "properties": {
63
+ "card_id": {
64
+ "type": "string",
65
+ "description": "Unique card identifier (e.g., CARD-001)."
66
+ },
67
+ "card_type": {
68
+ "type": "string",
69
+ "enum": ["pattern", "profile", "regression_watch", "false_positive", "fix_idiom"],
70
+ "description": "Semantic category of this context card."
71
+ },
72
+ "priority": {
73
+ "type": "integer",
74
+ "minimum": 1,
75
+ "maximum": 100,
76
+ "description": "Rank order priority (higher = more relevant/critical)."
77
+ },
78
+ "title": {
79
+ "type": "string",
80
+ "description": "Short, human-readable and agent-scannable card title."
81
+ },
82
+ "summary": {
83
+ "type": "string",
84
+ "description": "One-line operational summary for rapid agent reasoning."
85
+ },
86
+ "card_data": {
87
+ "type": "object",
88
+ "description": "Structured card payload containing rule_id, fix_strategy, confidence, affected_files, etc.",
89
+ "additionalProperties": true
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }