torusguard 1.3.5 → 1.4.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 (194) hide show
  1. package/.torusguard/.manifest.json +37 -36
  2. package/.torusguard/runs/report-latest.html +5862 -315
  3. package/.torusguard/runs/results-latest.sarif +20 -0
  4. package/.torusguard/runs/run-20260918-104221-audit/findings.json +1 -0
  5. package/.torusguard/runs/run-20260918-104221-audit/findings.md +8 -0
  6. package/.torusguard/runs/run-20260918-104221-audit/manifest.json +12 -0
  7. package/.torusguard/runs/run-20260918-104221-audit/summary.md +5 -0
  8. package/.torusguard/runs/run-20260918-104236-audit/findings.json +2314 -0
  9. package/.torusguard/runs/run-20260918-104236-audit/findings.md +960 -0
  10. package/.torusguard/runs/run-20260918-104236-audit/manifest.json +12 -0
  11. package/.torusguard/runs/run-20260918-104236-audit/summary.md +5 -0
  12. package/.torusguard/runs/run-20260918-105723-audit/findings.json +2382 -0
  13. package/.torusguard/runs/run-20260918-105723-audit/findings.md +960 -0
  14. package/.torusguard/runs/run-20260918-105723-audit/manifest.json +12 -0
  15. package/.torusguard/runs/run-20260918-105723-audit/summary.md +5 -0
  16. package/.torusguard/runs/run-20260918-105731-audit/findings.json +1 -0
  17. package/.torusguard/runs/run-20260918-105731-audit/findings.md +8 -0
  18. package/.torusguard/runs/run-20260918-105731-audit/manifest.json +12 -0
  19. package/.torusguard/runs/run-20260918-105731-audit/summary.md +5 -0
  20. package/.torusguard/runs/run-20260918-105940-audit/findings.json +1 -0
  21. package/.torusguard/runs/run-20260918-105940-audit/findings.md +8 -0
  22. package/.torusguard/runs/run-20260918-105940-audit/manifest.json +13 -0
  23. package/.torusguard/runs/run-20260918-105940-audit/remediation.md +7 -0
  24. package/.torusguard/runs/run-20260918-105940-audit/summary.md +5 -0
  25. package/.torusguard/runs/run-20260919-145701-audit/findings.json +1 -0
  26. package/.torusguard/runs/run-20260919-145701-audit/findings.md +8 -0
  27. package/.torusguard/runs/run-20260919-145701-audit/manifest.json +12 -0
  28. package/.torusguard/runs/run-20260919-145701-audit/summary.md +5 -0
  29. package/.torusguard/runs/run-20260919-151729-audit/findings.json +1 -0
  30. package/.torusguard/runs/run-20260919-151729-audit/findings.md +8 -0
  31. package/.torusguard/runs/run-20260919-151729-audit/manifest.json +13 -0
  32. package/.torusguard/runs/run-20260919-151729-audit/remediation.md +7 -0
  33. package/.torusguard/runs/run-20260919-151729-audit/summary.md +5 -0
  34. package/.torusguard/runs/run-20260919-152340-audit/findings.json +1 -0
  35. package/.torusguard/runs/run-20260919-152340-audit/findings.md +8 -0
  36. package/.torusguard/runs/run-20260919-152340-audit/manifest.json +12 -0
  37. package/.torusguard/runs/run-20260919-152340-audit/summary.md +5 -0
  38. package/.torusguard/runs/run-20260919-152345-audit/findings.json +1 -0
  39. package/.torusguard/runs/run-20260919-152345-audit/findings.md +8 -0
  40. package/.torusguard/runs/run-20260919-152345-audit/manifest.json +12 -0
  41. package/.torusguard/runs/run-20260919-152345-audit/summary.md +5 -0
  42. package/.torusguard/runs/run-20260919-153500-audit/findings.json +1 -0
  43. package/.torusguard/runs/run-20260919-153500-audit/findings.md +8 -0
  44. package/.torusguard/runs/run-20260919-153500-audit/manifest.json +12 -0
  45. package/.torusguard/runs/run-20260919-153500-audit/summary.md +5 -0
  46. package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  47. package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  48. package/.torusguard/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  49. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  50. package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  51. package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  52. package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  53. package/.torusguard/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  54. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  55. package/.torusguard/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  56. package/.torusguard/scripts/__pycache__/recipes_runner.cpython-314.pyc +0 -0
  57. package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  58. package/.torusguard/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  59. package/.torusguard/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  60. package/.torusguard/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  61. package/.torusguard/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  62. package/.torusguard/scripts/apply_runner.py +108 -9
  63. package/.torusguard/scripts/audit_runner.py +336 -24
  64. package/.torusguard/scripts/harden_runner.py +124 -70
  65. package/.torusguard/scripts/html_reporter.py +3585 -648
  66. package/.torusguard/scripts/manifest_builder.py +2 -0
  67. package/.torusguard/scripts/recheck_runner.py +5 -4
  68. package/.torusguard/scripts/recipes_runner.py +91 -8
  69. package/.torusguard/scripts/report_sync.py +496 -73
  70. package/.torusguard/scripts/sarif_exporter.py +48 -8
  71. package/.torusguard/scripts/stack_detect.py +44 -2
  72. package/.torusguard/scripts/status_runner.py +267 -0
  73. package/.torusguard/scripts/term_ui.py +1 -1
  74. package/.torusguard/skills/torusguard/SKILL.md +75 -72
  75. package/.torusguard/skills/torusguard-apply/SKILL.md +84 -80
  76. package/.torusguard/skills/torusguard-audit/SKILL.md +87 -83
  77. package/.torusguard/skills/torusguard-authorize/SKILL.md +7 -2
  78. package/.torusguard/skills/torusguard-exploit-check/SKILL.md +7 -2
  79. package/.torusguard/skills/torusguard-full/SKILL.md +7 -2
  80. package/.torusguard/skills/torusguard-harden/SKILL.md +98 -94
  81. package/.torusguard/skills/torusguard-init/SKILL.md +68 -64
  82. package/.torusguard/skills/torusguard-recheck/SKILL.md +81 -77
  83. package/.torusguard/skills/torusguard-report/SKILL.md +93 -72
  84. package/.torusguard/skills/torusguard-status/SKILL.md +62 -58
  85. package/.torusguard/skills/torusguard-verify/SKILL.md +7 -2
  86. package/.torusguard/skills/torusguard-web-validate/SKILL.md +7 -2
  87. package/.torusguard/workflows/apply.md +1 -1
  88. package/.torusguard/workflows/audit.md +1 -1
  89. package/.torusguard/workflows/authorize.md +1 -1
  90. package/.torusguard/workflows/exploit-check.md +1 -1
  91. package/.torusguard/workflows/harden.md +1 -1
  92. package/.torusguard/workflows/init.md +1 -1
  93. package/.torusguard/workflows/memory.md +1 -1
  94. package/.torusguard/workflows/recheck.md +1 -1
  95. package/.torusguard/workflows/report.md +1 -1
  96. package/.torusguard/workflows/status.md +1 -1
  97. package/.torusguard/workflows/verify.md +1 -1
  98. package/.torusguard/workflows/web-validate.md +1 -1
  99. package/README.md +115 -81
  100. package/bin/torusguard.js +244 -38
  101. package/package.json +6 -2
  102. package/skills/torusguard/SKILL.md +1 -1
  103. package/skills/torusguard/__pycache__/bootstrap.cpython-314.pyc +0 -0
  104. package/skills/torusguard/bootstrap.py +52 -8
  105. package/skills/torusguard/payload/.manifest.json +51 -36
  106. package/skills/torusguard/payload/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  107. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  108. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  109. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
  110. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  111. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  112. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  113. package/skills/torusguard/payload/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  114. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
  115. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  116. package/skills/torusguard/payload/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  117. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  118. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  119. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  120. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  121. package/skills/torusguard/payload/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  122. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  123. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  124. package/skills/torusguard/payload/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
  125. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
  126. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  127. package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  128. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
  129. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  130. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  131. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  132. package/skills/torusguard/payload/scripts/apply_runner.py +108 -9
  133. package/skills/torusguard/payload/scripts/audit_runner.py +336 -24
  134. package/skills/torusguard/payload/scripts/harden_runner.py +124 -70
  135. package/skills/torusguard/payload/scripts/html_reporter.py +3585 -648
  136. package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
  137. package/skills/torusguard/payload/scripts/recheck_runner.py +5 -4
  138. package/skills/torusguard/payload/scripts/recipes_runner.py +91 -8
  139. package/skills/torusguard/payload/scripts/report_sync.py +496 -73
  140. package/skills/torusguard/payload/scripts/sarif_exporter.py +48 -8
  141. package/skills/torusguard/payload/scripts/stack_detect.py +44 -2
  142. package/skills/torusguard/payload/scripts/status_runner.py +267 -0
  143. package/skills/torusguard/payload/scripts/term_ui.py +1 -1
  144. package/skills/torusguard/payload/skills/torusguard/SKILL.md +1 -1
  145. package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +1 -1
  146. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +1 -1
  147. package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +1 -1
  148. package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +1 -1
  149. package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +1 -1
  150. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +1 -1
  151. package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +1 -1
  152. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +1 -1
  153. package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +40 -23
  154. package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +1 -1
  155. package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +1 -1
  156. package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +1 -1
  157. package/skills/torusguard/payload/workflows/apply.md +9 -1
  158. package/skills/torusguard/payload/workflows/audit.md +8 -2
  159. package/skills/torusguard/payload/workflows/authorize.md +1 -1
  160. package/skills/torusguard/payload/workflows/exploit-check.md +1 -1
  161. package/skills/torusguard/payload/workflows/harden.md +6 -1
  162. package/skills/torusguard/payload/workflows/init.md +7 -1
  163. package/skills/torusguard/payload/workflows/memory.md +1 -1
  164. package/skills/torusguard/payload/workflows/recheck.md +1 -1
  165. package/skills/torusguard/payload/workflows/recipes.md +55 -0
  166. package/skills/torusguard/payload/workflows/report.md +59 -55
  167. package/skills/torusguard/payload/workflows/status.md +4 -1
  168. package/skills/torusguard/payload/workflows/torusguard-apply.md +110 -0
  169. package/skills/torusguard/payload/workflows/torusguard-audit.md +105 -0
  170. package/skills/torusguard/payload/workflows/torusguard-authorize.md +96 -0
  171. package/skills/torusguard/payload/workflows/torusguard-exploit-check.md +98 -0
  172. package/skills/torusguard/payload/workflows/torusguard-harden.md +104 -0
  173. package/skills/torusguard/payload/workflows/torusguard-init.md +106 -0
  174. package/skills/torusguard/payload/workflows/torusguard-recheck.md +101 -0
  175. package/skills/torusguard/payload/workflows/torusguard-recipes.md +55 -0
  176. package/skills/torusguard/payload/workflows/torusguard-report.md +105 -0
  177. package/skills/torusguard/payload/workflows/torusguard-status.md +103 -0
  178. package/skills/torusguard/payload/workflows/torusguard-verify.md +100 -0
  179. package/skills/torusguard/payload/workflows/torusguard-web-validate.md +96 -0
  180. package/skills/torusguard/payload/workflows/torusguard.md +19 -0
  181. package/skills/torusguard/payload/workflows/verify.md +1 -1
  182. package/skills/torusguard/payload/workflows/web-validate.md +1 -1
  183. package/skills/torusguard-apply/SKILL.md +1 -1
  184. package/skills/torusguard-audit/SKILL.md +1 -1
  185. package/skills/torusguard-authorize/SKILL.md +1 -1
  186. package/skills/torusguard-exploit-check/SKILL.md +1 -1
  187. package/skills/torusguard-full/SKILL.md +1 -1
  188. package/skills/torusguard-harden/SKILL.md +1 -1
  189. package/skills/torusguard-init/SKILL.md +1 -1
  190. package/skills/torusguard-recheck/SKILL.md +1 -1
  191. package/skills/torusguard-report/SKILL.md +40 -23
  192. package/skills/torusguard-status/SKILL.md +1 -1
  193. package/skills/torusguard-verify/SKILL.md +1 -1
  194. package/skills/torusguard-web-validate/SKILL.md +1 -1
@@ -9,6 +9,7 @@ import sys
9
9
  import json
10
10
  import hashlib
11
11
  import argparse
12
+ from pathlib import Path
12
13
  from typing import List, Dict, Any
13
14
 
14
15
  def generate_sarif(findings: List[Dict[str, Any]], run_id: str = "default", category: str = "torusguard/static") -> Dict[str, Any]:
@@ -76,7 +77,7 @@ def generate_sarif(findings: List[Dict[str, Any]], run_id: str = "default", cate
76
77
  "tool": {
77
78
  "driver": {
78
79
  "name": "TorusGuard",
79
- "semanticVersion": "1.3.5",
80
+ "semanticVersion": "1.3.6",
80
81
  "informationUri": "https://github.com/githubmofo/TorusGuard",
81
82
  "rules": list(rules_map.values())
82
83
  }
@@ -95,22 +96,61 @@ def main():
95
96
  parser = argparse.ArgumentParser(description="TorusGuard SARIF v2.1.0 Exporter")
96
97
  parser.add_argument("--input", "-i", help="Path to findings JSON file")
97
98
  parser.add_argument("--output", "-o", help="Output path for sarif.json")
98
- parser.add_argument("--run-id", default="run-default", help="Unique execution Run ID")
99
+ parser.add_argument("--root", "-r", help="Project root override")
100
+ parser.add_argument("--run-id", default=None, help="Unique execution Run ID")
101
+ parser.add_argument("--stdout", action="store_true", help="Print SARIF JSON to stdout")
99
102
  args = parser.parse_args()
100
103
 
104
+ root = Path(args.root).resolve() if args.root else Path.cwd().resolve()
101
105
  findings = []
106
+ run_id = args.run_id or "run-default"
107
+
102
108
  if args.input:
103
- with open(args.input, "r", encoding="utf-8") as f:
104
- findings = json.load(f)
109
+ in_path = Path(args.input)
110
+ if not in_path.is_absolute():
111
+ in_path = (root / in_path).resolve()
112
+ if in_path.is_file():
113
+ with open(in_path, "r", encoding="utf-8") as f:
114
+ findings = json.load(f)
115
+ else:
116
+ # Auto-discover latest audit run findings
117
+ runs_dir = root / ".torusguard" / "runs"
118
+ if runs_dir.is_dir():
119
+ run_folders = sorted(
120
+ [d for d in runs_dir.iterdir() if d.is_dir() and (d / "findings.json").is_file()],
121
+ key=lambda p: p.stat().st_mtime,
122
+ reverse=True
123
+ )
124
+ if run_folders:
125
+ latest_run = run_folders[0]
126
+ run_id = args.run_id or latest_run.name
127
+ findings_file = latest_run / "findings.json"
128
+ try:
129
+ with open(findings_file, "r", encoding="utf-8") as f:
130
+ findings = json.load(f)
131
+ except Exception:
132
+ findings = []
105
133
 
106
- sarif = generate_sarif(findings, run_id=args.run_id)
134
+ sarif = generate_sarif(findings, run_id=run_id)
107
135
 
108
136
  if args.output:
109
- with open(args.output, "w", encoding="utf-8") as f:
137
+ out_path = Path(args.output)
138
+ if not out_path.is_absolute():
139
+ out_path = (root / out_path).resolve()
140
+ out_path.parent.mkdir(parents=True, exist_ok=True)
141
+ with open(out_path, "w", encoding="utf-8") as f:
110
142
  json.dump(sarif, f, indent=2)
111
- print(f"SARIF log written to: {args.output}")
112
- else:
143
+ print(f"[SUCCESS] SARIF log written to: {out_path}")
144
+ elif args.stdout:
113
145
  print(json.dumps(sarif, indent=2))
146
+ else:
147
+ # Default to writing in .torusguard/runs/results-latest.sarif
148
+ default_sarif = root / ".torusguard" / "runs" / "results-latest.sarif"
149
+ default_sarif.parent.mkdir(parents=True, exist_ok=True)
150
+ with open(default_sarif, "w", encoding="utf-8") as f:
151
+ json.dump(sarif, f, indent=2)
152
+ print(f"[SUCCESS] SARIF log written to: {default_sarif}")
153
+
114
154
 
115
155
  if __name__ == "__main__":
116
156
  main()
@@ -221,6 +221,24 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
221
221
  "indicator": "Flask application instantiation"
222
222
  })
223
223
  profile["recommended_references"].append("flask-security.md")
224
+ elif "tornado" in content or "tornado.web" in content:
225
+ add_to_list(profile, "languages_found", "Python")
226
+ profile["ecosystem_family"] = "python"
227
+ add_to_list(profile, "frameworks_found", "Tornado")
228
+ profile["confidence"] = "Confirmed"
229
+ profile["detection_evidence"].append({
230
+ "file": str(py_file.relative_to(project_root)),
231
+ "indicator": "Tornado application"
232
+ })
233
+ elif "starlette" in content:
234
+ add_to_list(profile, "languages_found", "Python")
235
+ profile["ecosystem_family"] = "python"
236
+ add_to_list(profile, "frameworks_found", "Starlette")
237
+ profile["confidence"] = "Confirmed"
238
+ profile["detection_evidence"].append({
239
+ "file": str(py_file.relative_to(project_root)),
240
+ "indicator": "Starlette application"
241
+ })
224
242
 
225
243
  if "sqlalchemy" in content:
226
244
  add_to_list(profile, "data_layers_found", "SQLAlchemy")
@@ -286,11 +304,27 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
286
304
  profile["confidence"] = "Confirmed"
287
305
  profile["detection_evidence"].append({"file": "package.json", "indicator": "express dependency"})
288
306
  profile["recommended_references"].append("express-security.md")
307
+ elif "fastify" in deps:
308
+ add_to_list(profile, "frameworks_found", "Fastify")
309
+ profile["confidence"] = "Confirmed"
310
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "fastify dependency"})
311
+ elif "koa" in deps:
312
+ add_to_list(profile, "frameworks_found", "Koa")
313
+ profile["confidence"] = "Confirmed"
314
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "koa dependency"})
315
+ elif "@remix-run/react" in deps or "@remix-run/node" in deps:
316
+ add_to_list(profile, "frameworks_found", "Remix")
317
+ profile["confidence"] = "Confirmed"
318
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "Remix dependency"})
289
319
  elif "react" in deps:
290
320
  add_to_list(profile, "frameworks_found", "React / Vite")
291
321
  profile["confidence"] = "Confirmed"
292
322
  profile["detection_evidence"].append({"file": "package.json", "indicator": "react dependency"})
293
323
  profile["recommended_references"].append("react-vite-security.md")
324
+ elif "vite" in deps:
325
+ add_to_list(profile, "frameworks_found", "Vite")
326
+ profile["confidence"] = "Confirmed"
327
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "vite dependency"})
294
328
 
295
329
  # ORM / Data layer detection
296
330
  if "@prisma/client" in deps or "prisma" in deps:
@@ -433,6 +467,8 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
433
467
 
434
468
  if "Microsoft.NET.Sdk.Web" in csproj_content or "Microsoft.AspNetCore" in csproj_content or "Swashbuckle" in csproj_content:
435
469
  add_to_list(profile, "frameworks_found", "ASP.NET Core")
470
+ if list(project_root.glob("**/*.razor")) or "Microsoft.AspNetCore.Components" in csproj_content or "blazor" in csproj_content.lower():
471
+ add_to_list(profile, "frameworks_found", "Blazor")
436
472
  if "Microsoft.EntityFrameworkCore" in csproj_content:
437
473
  add_to_list(profile, "data_layers_found", "Entity Framework Core")
438
474
  elif "Dapper" in csproj_content:
@@ -442,11 +478,17 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
442
478
  # G. PHP Ecosystem
443
479
  # -------------------------------------------------------------------------
444
480
  composer_json = project_root / "composer.json"
445
- if composer_json.is_file():
481
+ is_wordpress = (project_root / "wp-config.php").is_file() or (project_root / "wp-load.php").is_file() or (project_root / "wp-content").is_dir()
482
+ if composer_json.is_file() or is_wordpress:
446
483
  add_to_list(profile, "languages_found", "PHP")
447
484
  profile["ecosystem_family"] = "php"
448
485
  profile["confidence"] = "Confirmed"
449
- profile["detection_evidence"].append({"file": "composer.json", "indicator": "PHP Composer manifest"})
486
+ if is_wordpress:
487
+ add_to_list(profile, "frameworks_found", "WordPress")
488
+ add_to_list(profile, "data_layers_found", "MySQL / wpdb")
489
+ profile["detection_evidence"].append({"file": "wp-config.php" if (project_root / "wp-config.php").is_file() else "wp-content", "indicator": "WordPress installation"})
490
+ if composer_json.is_file():
491
+ profile["detection_evidence"].append({"file": "composer.json", "indicator": "PHP Composer manifest"})
450
492
  profile["recommended_rules"].extend(["TG-SEC-*", "TG-INPUT-001", "TG-INPUT-002", "TG-PLATFORM-*"])
451
493
  profile["recommended_references"].append("polyglot-security-matrix.md")
452
494
 
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Diagnostic Status Engine (v1.4.0)
4
+ Displays workspace security posture, detected stack, active rules, historical runs,
5
+ golden recipes, and runtime scope validity in mathematically aligned 75-column cards.
6
+ Adheres to Python Pro & Python Patterns standards.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import sys
12
+ import json
13
+ import argparse
14
+ from pathlib import Path
15
+ from dataclasses import dataclass, asdict
16
+ from typing import Any
17
+
18
+ # Import term_ui for 75-column card formatting
19
+ try:
20
+ from term_ui import (
21
+ BOLD, DIM, RESET, CYAN, GREEN, YELLOW, WHITE, GRAY, RED,
22
+ card_header, card_border_top, card_border_bottom, card_divider, format_box_line
23
+ )
24
+ except ImportError:
25
+ scripts_dir = Path(__file__).resolve().parent
26
+ if str(scripts_dir) not in sys.path:
27
+ sys.path.insert(0, str(scripts_dir))
28
+ from term_ui import (
29
+ BOLD, DIM, RESET, CYAN, GREEN, YELLOW, WHITE, GRAY, RED,
30
+ card_header, card_border_top, card_border_bottom, card_divider, format_box_line
31
+ )
32
+
33
+
34
+ @dataclass
35
+ class WorkspaceStatus:
36
+ version: str
37
+ target_path: str
38
+ is_initialized: bool
39
+ stack_detected: str
40
+ active_rules_count: int
41
+ total_runs_count: int
42
+ latest_run_id: str | None
43
+ latest_run_time: str | None
44
+ latest_findings: int
45
+ golden_recipes_count: int
46
+ scope_status: str
47
+ health_score: int
48
+ posture_status: str
49
+
50
+ def to_dict(self) -> dict[str, Any]:
51
+ return asdict(self)
52
+
53
+
54
+ def collect_status(target_dir: Path) -> WorkspaceStatus:
55
+ """Inspect workspace configuration and filesystem records to construct status snapshot."""
56
+ target_dir = target_dir.resolve()
57
+ tg_dir = target_dir / ".torusguard"
58
+ is_init = tg_dir.is_dir()
59
+
60
+ # 1. Read config
61
+ version = "1.4.0"
62
+ stack_name = "Undetected"
63
+ cfg_file = tg_dir / "config" / "torusguard.json"
64
+ if cfg_file.is_file():
65
+ try:
66
+ with open(cfg_file, "r", encoding="utf-8") as f:
67
+ cfg = json.load(f)
68
+ version = cfg.get("version", version)
69
+ stack_name = cfg.get("stack", stack_name)
70
+ except (json.JSONDecodeError, OSError):
71
+ pass
72
+
73
+ if stack_name in ("Undetected", "Unknown", "None", ""):
74
+ try:
75
+ from stack_detect import detect_stack
76
+ p = detect_stack(target_dir)
77
+ parts = []
78
+ if p.get("language") and p["language"] != "Unknown":
79
+ parts.append(p["language"])
80
+ if p.get("framework") and p["framework"] != "None":
81
+ parts.append(p["framework"])
82
+ if parts:
83
+ stack_name = " / ".join(parts)
84
+ except Exception:
85
+ pass
86
+
87
+ # 2. Count active rules
88
+ active_rules_count = 0
89
+ active_rules_dir = tg_dir / "rules" / "active"
90
+ if active_rules_dir.is_dir():
91
+ active_rules_count = sum(1 for f in active_rules_dir.glob("*.md"))
92
+ if active_rules_count == 0:
93
+ rules_root = tg_dir / "rules"
94
+ if rules_root.is_dir():
95
+ active_rules_count = sum(1 for f in rules_root.rglob("TG-*.md"))
96
+ if active_rules_count == 0:
97
+ active_rules_count = 74 # Canonical rule catalog default
98
+
99
+ # 3. Read run history
100
+ total_runs = 0
101
+ latest_run_id: str | None = None
102
+ latest_run_time: str | None = None
103
+ latest_findings = 0
104
+ runs_dir = tg_dir / "runs"
105
+ if runs_dir.is_dir():
106
+ run_folders = [d for d in runs_dir.iterdir() if d.is_dir() and d.name.startswith("run-")]
107
+ run_folders.sort(key=lambda d: d.name, reverse=True)
108
+ total_runs = len(run_folders)
109
+ if run_folders:
110
+ latest = run_folders[0]
111
+ latest_run_id = latest.name
112
+ manifest_file = latest / "manifest.json"
113
+ if manifest_file.is_file():
114
+ try:
115
+ with open(manifest_file, "r", encoding="utf-8") as f:
116
+ m = json.load(f)
117
+ latest_run_time = m.get("created_at", latest.name)
118
+ latest_findings = m.get("findings_count", 0)
119
+ except (json.JSONDecodeError, OSError):
120
+ pass
121
+
122
+ # 4. Golden recipes in persistent memory
123
+ golden_recipes_count = 0
124
+ patterns_file = tg_dir / "memory" / "patterns.json"
125
+ if patterns_file.is_file():
126
+ try:
127
+ with open(patterns_file, "r", encoding="utf-8") as f:
128
+ p_data = json.load(f)
129
+ if isinstance(p_data, list):
130
+ golden_recipes_count = sum(
131
+ 1 for p in p_data
132
+ if isinstance(p, dict) and (
133
+ p.get("pattern_type") == "golden_fix_recipe" or "recipe_data" in p or "recipe_id" in p
134
+ )
135
+ )
136
+ elif isinstance(p_data, dict):
137
+ golden_recipes_count = len(p_data.get("golden_recipes", []))
138
+ except (json.JSONDecodeError, OSError):
139
+ pass
140
+
141
+ # 5. Scope authorization
142
+ scope_status = "Unconfigured"
143
+ scope_file = tg_dir / "config" / "scope.json"
144
+ if scope_file.is_file():
145
+ try:
146
+ with open(scope_file, "r", encoding="utf-8") as f:
147
+ s_data = json.load(f)
148
+ expires_at = s_data.get("expires_at")
149
+ if expires_at:
150
+ scope_status = "Authorized (TTL Active)"
151
+ else:
152
+ scope_status = "Authorized (Static)"
153
+ except (json.JSONDecodeError, OSError):
154
+ scope_status = "Error reading scope"
155
+
156
+ # 6. Posture health from security_report.md
157
+ health_score = 100
158
+ posture = "CLEAN & SECURE"
159
+ report_file = target_dir / "security_report.md"
160
+ if report_file.is_file():
161
+ try:
162
+ content = report_file.read_text(encoding="utf-8")
163
+ import re
164
+ m = re.search(r"Posture Score:\s*`(\d+)/100`", content)
165
+ if m:
166
+ health_score = int(m.group(1))
167
+ m_stat = re.search(r"Posture Status:\s*`([^`]+)`", content)
168
+ if m_stat:
169
+ posture = m_stat.group(1)
170
+ except OSError:
171
+ pass
172
+
173
+ if health_score < 70:
174
+ posture = "ACTION NEEDED"
175
+ elif health_score < 90:
176
+ posture = "ELEVATED RISK"
177
+ elif health_score == 100:
178
+ posture = "CLEAN & SECURE"
179
+
180
+ return WorkspaceStatus(
181
+ version=version,
182
+ target_path=str(target_dir),
183
+ is_initialized=is_init,
184
+ stack_detected=stack_name,
185
+ active_rules_count=active_rules_count,
186
+ total_runs_count=total_runs,
187
+ latest_run_id=latest_run_id,
188
+ latest_run_time=latest_run_time,
189
+ latest_findings=latest_findings,
190
+ golden_recipes_count=golden_recipes_count,
191
+ scope_status=scope_status,
192
+ health_score=health_score,
193
+ posture_status=posture,
194
+ )
195
+
196
+
197
+ def print_status_card(status: WorkspaceStatus) -> None:
198
+ """Render standardized 75-column diagnostic status cards."""
199
+ print()
200
+ print(card_header(
201
+ "🛡️ T O R U S G U A R D S T A T U S",
202
+ "Workspace Diagnostic Overview & Posture Snapshot",
203
+ f"v{status.version}"
204
+ ))
205
+ print()
206
+
207
+ # Card 1: Workspace & Stack
208
+ print(card_border_top("Workspace Environment", CYAN))
209
+ init_str = f"{GREEN}Initialized (.torusguard/ active){RESET}" if status.is_initialized else f"{RED}Uninitialized (Run: npx torusguard init){RESET}"
210
+ print(format_box_line(f"Workspace: {WHITE}{status.target_path}{RESET}", 67))
211
+ print(format_box_line(f"Status: {init_str}", 67))
212
+ print(format_box_line(f"Stack: {BOLD}{WHITE}{status.stack_detected}{RESET}", 67))
213
+ print(format_box_line(f"Active Rules: {GREEN}{status.active_rules_count}{RESET} canonical rules enabled across 18 families", 67))
214
+ print(card_border_bottom(CYAN))
215
+ print()
216
+
217
+ # Card 2: Run History & Memory
218
+ print(card_border_top("Run History & Memory Engine", YELLOW))
219
+ print(format_box_line(f"Total Runs: {WHITE}{status.total_runs_count}{RESET} historical audit runs", 67, border_color=YELLOW))
220
+ if status.latest_run_id:
221
+ print(format_box_line(f"Latest Run: {CYAN}{status.latest_run_id}{RESET}", 67, border_color=YELLOW))
222
+ print(format_box_line(f"Run Timestamp: {DIM}{status.latest_run_time or 'N/A'}{RESET}", 67, border_color=YELLOW))
223
+ print(format_box_line(f"Run Findings: {WHITE}{status.latest_findings}{RESET} vulnerabilities discovered", 67, border_color=YELLOW))
224
+ else:
225
+ print(format_box_line(f"Latest Run: {DIM}No runs recorded yet (Run: npx torusguard audit){RESET}", 67, border_color=YELLOW))
226
+ print(format_box_line(f"Golden Recipes: {GREEN}{status.golden_recipes_count}{RESET} verified fix patterns distilled in memory", 67, border_color=YELLOW))
227
+ print(format_box_line(f"Runtime Scope: {WHITE}{status.scope_status}{RESET}", 67, border_color=YELLOW))
228
+ print(card_border_bottom(YELLOW))
229
+ print()
230
+
231
+ # Card 3: Security Posture
232
+ posture_color = GREEN if status.health_score >= 90 else (YELLOW if status.health_score >= 70 else RED)
233
+ print(card_border_top("Security Health Posture", posture_color, double=True))
234
+ print(format_box_line(f"Health Score: {posture_color}{BOLD}{status.health_score}/100{RESET}", 67, border="║", border_color=posture_color))
235
+ print(format_box_line(f"Posture State: {posture_color}{BOLD}{status.posture_status}{RESET}", 67, border="║", border_color=posture_color))
236
+ print(format_box_line(f"Living Ledger: {CYAN}security_report.md (Synchronized){RESET}", 67, border="║", border_color=posture_color))
237
+ print(card_border_bottom(posture_color, double=True))
238
+ print()
239
+
240
+ # Quick Next Actions
241
+ print(card_border_top("Available Lifecycle Actions", GRAY))
242
+ print(format_box_line(f"Audit Codebase: {GREEN}npx torusguard audit{RESET}", 67, border_color=GRAY))
243
+ print(format_box_line(f"Harden Patches: {GREEN}npx torusguard harden{RESET}", 67, border_color=GRAY))
244
+ print(format_box_line(f"View Recipes: {GREEN}npx torusguard recipes{RESET}", 67, border_color=GRAY))
245
+ print(format_box_line(f"HTML Dashboard: {GREEN}npx torusguard report --html{RESET}", 67, border_color=GRAY))
246
+ print(card_border_bottom(GRAY))
247
+ print()
248
+
249
+
250
+ def main() -> None:
251
+ parser = argparse.ArgumentParser(description="TorusGuard Workspace Diagnostic Status Engine")
252
+ parser.add_argument("path", nargs="?", default=".", help="Target project root directory")
253
+ parser.add_argument("--target", "-t", help="Target project root directory (alias for path)")
254
+ parser.add_argument("--json", action="store_true", help="Output raw JSON snapshot")
255
+ args = parser.parse_args()
256
+
257
+ target = Path(args.target or args.path).resolve()
258
+ status = collect_status(target)
259
+
260
+ if args.json:
261
+ print(json.dumps(status.to_dict(), indent=2))
262
+ else:
263
+ print_status_card(status)
264
+
265
+
266
+ if __name__ == "__main__":
267
+ main()
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- TorusGuard Unified Terminal UI Engine (v1.3.5)
3
+ TorusGuard Unified Terminal UI Engine (v1.3.6)
4
4
  Provides mathematically exact 75-column card formatting, ANSI-stripping,
5
5
  Unicode/emoji visual width calculation, and visual truncation with ellipsis.
6
6
  Pure Python 3.10+ standard library (zero external dependencies).
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard
3
3
  description: Universal autonomous security engine: 74 canonical rules across 18 families, polyglot stack detection across 16+ languages, Ponytail remediation bounds (<=35 add, <=25 del), standardized 75-column terminal UI, SARIF v2.1.0 exports, and persistent security memory context.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  ---
6
6
 
7
7
  # TorusGuard Master Security Engine & Command Router
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-apply
3
3
  description: Apply governed remediation patches to disk with pre-apply rollback snapshots and Human Gate validation via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/apply.md
6
6
  tools: Read, Grep, Glob, Write, replace_file_content, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-audit
3
3
  description: Static AST security scanning, line-shift invariant fingerprinting, root-cause clustering, and 0-100 confidence scoring via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/audit.md
6
6
  tools: Read, Grep, Glob, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-authorize
3
3
  description: Register and validate runtime target authorization boundaries — scope boundaries, ownership proofs, TTL expiration, and Safety Gate enforcement.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/authorize.md
6
6
  tools: Read, Grep, Glob, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-exploit-check
3
3
  description: Safe, non-destructive confirmation of exploitability using inert canary tokens and sentinels.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/exploit-check.md
6
6
  tools: Read, Grep, Glob, Bash, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-full
3
3
  description: Master 7-stage security pipeline orchestrator — coordinates discovery, authorization, static audit, runtime validation, governed remediation, recheck, and reporting.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/audit.md
6
6
  tools: Read, Grep, Glob, Bash, Edit, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-harden
3
3
  description: Package surgical remediation bundles conforming to the Ponytail Protocol (<= 35 additions, <= 25 deletions) via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/harden.md
6
6
  tools: Read, Grep, Glob, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-init
3
3
  description: Initialize TorusGuard workspace — detect project stack, activate tailored TG-* security rules, and generate SECURITY.md baseline via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/init.md
6
6
  tools: Read, Grep, Glob, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-recheck
3
3
  description: Execute targeted differential AST re-scan against modified files, verify fix closure, and assert zero regressions via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/recheck.md
6
6
  tools: Read, Grep, Glob, Write, run_command
7
7
  scripts-binding:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-report
3
3
  description: Generate executive posture reports, export OASIS SARIF v2.1.0 logs, and render dark-mode HTML dashboards via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 2.2.0
5
5
  workflow: .torusguard/workflows/report.md
6
6
  tools: Read, Grep, Glob, Write, run_command
7
7
  scripts-binding:
@@ -15,61 +15,78 @@ scripts-binding:
15
15
  # TorusGuard Report — Posture Reporting & SARIF / HTML Export
16
16
 
17
17
  ## Objective
18
- Aggregate findings, verification traces, and recheck results into an auditable executive security report, export schema-compliant OASIS SARIF v2.1.0 logs for CI/CD pipelines, and render zero-dependency single-file visual HTML posture reports.
18
+ Aggregate findings, verification traces, and recheck results into an auditable executive security report, export schema-compliant OASIS SARIF v2.1.0 logs for CI/CD pipelines, and render zero-dependency single-file visual HTML posture reports with full dual-mode parity.
19
19
 
20
20
  ---
21
21
 
22
- ## Two Execution Modes
22
+ ## Execution Steps
23
23
 
24
24
  ### Mode A: Automated CLI Execution
25
25
  Run the report engine from your terminal:
26
26
  ```bash
27
- # Generate visual dark-mode HTML dashboard
27
+ # Generate visual dark-mode HTML dashboard (defaults to report.html at project root)
28
28
  npx torusguard report --html
29
29
 
30
30
  # Export OASIS SARIF v2.1.0 for GitHub Code Scanning / CI
31
31
  npx torusguard report --sarif
32
32
 
33
- # Generate both HTML and SARIF for latest run
33
+ # Generate both HTML and SARIF in a single pass
34
34
  npx torusguard report --html --sarif
35
35
 
36
- # Generate report for a specific project directory
37
- npx torusguard report ./examples/vulnerable-react-express --html
36
+ # Custom HTML output location
37
+ npx torusguard report --html --out ./docs/security-audit.html
38
38
 
39
- # Target a specific run ID
40
- npx torusguard report --run run-20260910-121618-audit --html
39
+ # Target a specific subproject / monorepo package
40
+ npx torusguard report --target ./apps/api --html
41
41
  ```
42
+
42
43
  **Under the Hood:**
43
- - Invokes `python .torusguard/scripts/html_reporter.py` to compile self-contained, offline-ready HTML reports with dynamic filtering, posture gauge, and cluster summaries at `.torusguard/runs/<run_id>/report.html`.
44
- - Invokes `python .torusguard/scripts/sarif_exporter.py` to produce OASIS SARIF v2.1.0 logs at `.torusguard/runs/<run_id>/results.sarif`.
44
+ - Invokes `python .torusguard/scripts/html_reporter.py` to compile self-contained, offline-ready HTML reports with dynamic filtering, posture gauge, directory attack surface heatmap, and golden recipe explorer at `report.html` (workspace root) and mirrors to `.torusguard/runs/report-latest.html`.
45
+ - Invokes `python .torusguard/scripts/sarif_exporter.py` to produce OASIS SARIF v2.1.0 logs at `.torusguard/runs/results-latest.sarif`.
45
46
  - Finalizes `manifest.json` metrics and updates historical posture scoring.
46
- - Displays 75-column terminal cards.
47
+ - Displays standardized 75-column terminal cards adhering to visual width invariants.
47
48
 
48
49
  ### Mode B: In-Session AI Chat Agent Reporting
49
50
  When generating security posture summaries in AI chat:
50
51
  1. **Aggregate Run Data:** Inspect `findings.json`, `remediation.md`, and `recheck.md` from the active run.
51
- 2. **Calculate Posture Score:** Compute posture score ($0$–$100$) based on severity weighting (Critical: 25, High: 15, Medium: 5, Low: 2).
52
+ 2. **Calculate Posture Score:** Compute posture score ($0$–$100$) based on severity weighting (Critical: 25, High: 15, Medium: 5, Low: 2). Clean repositories earn 100/100 across 74 defended invariants.
52
53
  3. **Format Executive Card:** Present finding counts, closed vulnerabilities, remaining risks, and compliance posture.
53
- 4. **Export Artifacts:** Verify that `report.html` and `results.sarif` are serialized to disk.
54
+ 4. **Export Artifacts:** Verify that `report.html` and `results-latest.sarif` are serialized to disk.
55
+ 5. **Keep Living Ledger in Lockstep:** Ensure `security_report.md` reflects all findings and verified closures.
56
+
57
+ ---
58
+
59
+ ## Zero-CDN & Offline Guarantee
60
+ - Zero external `<script>` or `<link>` tags. All styles, fonts, SVG icons, and scripts are embedded directly inside `report.html`.
61
+ - Full offline inspection: can be opened directly via `file:///` without an active internet connection.
62
+ - In-browser artifact downloads (SARIF v2.1.0 and CSV) use native `URL.createObjectURL(new Blob(...))` with zero network calls.
54
63
 
55
64
  ---
56
65
 
57
- ## SARIF v2.1.0 Specification
66
+ ## SARIF v2.1.0 Output Specification
58
67
  - **Schema:** `https://docs.oasis-open.org/sarif/sarif/v2.1.0/cos02/schemas/sarif-schema-2.1.0.json`
59
- - **Tool Driver:** `name: TorusGuard`, `semanticVersion: 1.3.5`, full rules catalog in `driver.rules`.
68
+ - **Tool Driver:** `name: TorusGuard`, `semanticVersion: 1.3.6`, full rules catalog in `driver.rules`.
60
69
  - **Automation Details:** `automationDetails.id: "torusguard/static"` to avoid collisions in multi-scanner CI/CD pipelines.
61
70
  - **Fingerprints:** `partialFingerprints.primaryLocationLineHash` with SHA-256 context hash.
62
71
 
63
72
  ---
64
73
 
65
- ## Output Card Format
74
+ ## Safety Constraints
75
+ - Never display raw secrets, tokens, or credentials in terminal outputs or emitted reports.
76
+ - Enforce read-only state for `report` actions — never modify source code during report generation.
77
+ - Ensure atomic writes with fallback retry to prevent corrupt reports during concurrent browser viewing.
78
+ - Respect monorepo target boundaries when `--target` is specified.
79
+
80
+ ---
81
+
82
+ ## Output Format
66
83
  ```markdown
67
- ### 📊 TorusGuard Security Posture Report Emitted
68
- - **Run ID:** `run-20260910-121618-audit`
69
- - **Posture Score:** 85 / 100 (HIGH SECURITY)
70
- - **Findings Summary:** 3 Evaluated · 2 Confirmed Fixed · 1 Unresolved
71
- - **HTML Dashboard:** `.torusguard/runs/<run_id>/report.html` (View in browser)
72
- - **SARIF v2.1.0 Export:** `.torusguard/runs/<run_id>/results.sarif` (Ready for CI)
84
+ ### 🛡️ TorusGuard Security Posture Report Emitted
85
+ - **Posture Score:** 100 / 100 (OPTIMAL DEFENSE)
86
+ - **Invariants Defended:** 74 Defended · 0 Harmed (74 Rules)
87
+ - **HTML Dashboard:** `report.html` (View in browser)
88
+ - **SARIF v2.1.0 Export:** `.torusguard/runs/results-latest.sarif` (Ready for CI)
89
+ - **Living Ledger:** `security_report.md` (Synchronized in lockstep)
73
90
  ```
74
91
 
75
92
  ## Living Report Ground Truth
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: torusguard-status
3
3
  description: Display current TorusGuard security posture, active configuration, rules catalog, and run history via CLI or AI Agent.
4
- version: 1.3.5
4
+ version: 1.3.6
5
5
  workflow: .torusguard/workflows/status.md
6
6
  tools: Read, Grep, Glob, run_command, Write
7
7
  scripts-binding: