torusguard 1.3.5 → 1.3.6

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 (152) hide show
  1. package/.torusguard/.manifest.json +35 -35
  2. package/.torusguard/runs/report-latest.html +2685 -303
  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 +12 -0
  23. package/.torusguard/runs/run-20260918-105940-audit/summary.md +5 -0
  24. package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  25. package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  26. package/.torusguard/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  27. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  28. package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  29. package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  30. package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  31. package/.torusguard/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  32. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  33. package/.torusguard/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  34. package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  35. package/.torusguard/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  36. package/.torusguard/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  37. package/.torusguard/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  38. package/.torusguard/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  39. package/.torusguard/scripts/apply_runner.py +11 -5
  40. package/.torusguard/scripts/audit_runner.py +222 -15
  41. package/.torusguard/scripts/harden_runner.py +3 -3
  42. package/.torusguard/scripts/html_reporter.py +2668 -648
  43. package/.torusguard/scripts/recheck_runner.py +3 -3
  44. package/.torusguard/scripts/recipes_runner.py +3 -3
  45. package/.torusguard/scripts/report_sync.py +370 -74
  46. package/.torusguard/scripts/sarif_exporter.py +48 -8
  47. package/.torusguard/scripts/stack_detect.py +44 -2
  48. package/.torusguard/scripts/term_ui.py +1 -1
  49. package/.torusguard/skills/torusguard/SKILL.md +75 -72
  50. package/.torusguard/skills/torusguard-apply/SKILL.md +84 -80
  51. package/.torusguard/skills/torusguard-audit/SKILL.md +87 -83
  52. package/.torusguard/skills/torusguard-authorize/SKILL.md +7 -2
  53. package/.torusguard/skills/torusguard-exploit-check/SKILL.md +7 -2
  54. package/.torusguard/skills/torusguard-full/SKILL.md +7 -2
  55. package/.torusguard/skills/torusguard-harden/SKILL.md +98 -94
  56. package/.torusguard/skills/torusguard-init/SKILL.md +68 -64
  57. package/.torusguard/skills/torusguard-recheck/SKILL.md +81 -77
  58. package/.torusguard/skills/torusguard-report/SKILL.md +93 -72
  59. package/.torusguard/skills/torusguard-status/SKILL.md +62 -58
  60. package/.torusguard/skills/torusguard-verify/SKILL.md +7 -2
  61. package/.torusguard/skills/torusguard-web-validate/SKILL.md +7 -2
  62. package/.torusguard/workflows/apply.md +1 -1
  63. package/.torusguard/workflows/audit.md +1 -1
  64. package/.torusguard/workflows/authorize.md +1 -1
  65. package/.torusguard/workflows/exploit-check.md +1 -1
  66. package/.torusguard/workflows/harden.md +1 -1
  67. package/.torusguard/workflows/init.md +1 -1
  68. package/.torusguard/workflows/memory.md +1 -1
  69. package/.torusguard/workflows/recheck.md +1 -1
  70. package/.torusguard/workflows/report.md +1 -1
  71. package/.torusguard/workflows/status.md +1 -1
  72. package/.torusguard/workflows/verify.md +1 -1
  73. package/.torusguard/workflows/web-validate.md +1 -1
  74. package/README.md +14 -8
  75. package/bin/torusguard.js +56 -20
  76. package/package.json +1 -1
  77. package/skills/torusguard/SKILL.md +1 -1
  78. package/skills/torusguard/bootstrap.py +7 -2
  79. package/skills/torusguard/payload/.manifest.json +35 -35
  80. package/skills/torusguard/payload/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  81. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  82. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  83. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
  84. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  85. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  86. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  87. package/skills/torusguard/payload/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  88. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
  89. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  90. package/skills/torusguard/payload/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  91. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  92. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  93. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  94. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  95. package/skills/torusguard/payload/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  96. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  97. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  98. package/skills/torusguard/payload/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
  99. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
  100. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  101. package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  102. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
  103. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  104. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  105. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  106. package/skills/torusguard/payload/scripts/apply_runner.py +11 -5
  107. package/skills/torusguard/payload/scripts/audit_runner.py +222 -15
  108. package/skills/torusguard/payload/scripts/harden_runner.py +3 -3
  109. package/skills/torusguard/payload/scripts/html_reporter.py +2668 -648
  110. package/skills/torusguard/payload/scripts/recheck_runner.py +3 -3
  111. package/skills/torusguard/payload/scripts/recipes_runner.py +3 -3
  112. package/skills/torusguard/payload/scripts/report_sync.py +370 -74
  113. package/skills/torusguard/payload/scripts/sarif_exporter.py +48 -8
  114. package/skills/torusguard/payload/scripts/stack_detect.py +44 -2
  115. package/skills/torusguard/payload/scripts/term_ui.py +1 -1
  116. package/skills/torusguard/payload/skills/torusguard/SKILL.md +1 -1
  117. package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +1 -1
  118. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +1 -1
  119. package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +1 -1
  120. package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +1 -1
  121. package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +1 -1
  122. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +1 -1
  123. package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +1 -1
  124. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +1 -1
  125. package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +40 -23
  126. package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +1 -1
  127. package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +1 -1
  128. package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +1 -1
  129. package/skills/torusguard/payload/workflows/apply.md +1 -1
  130. package/skills/torusguard/payload/workflows/audit.md +1 -1
  131. package/skills/torusguard/payload/workflows/authorize.md +1 -1
  132. package/skills/torusguard/payload/workflows/exploit-check.md +1 -1
  133. package/skills/torusguard/payload/workflows/harden.md +1 -1
  134. package/skills/torusguard/payload/workflows/init.md +1 -1
  135. package/skills/torusguard/payload/workflows/memory.md +1 -1
  136. package/skills/torusguard/payload/workflows/recheck.md +1 -1
  137. package/skills/torusguard/payload/workflows/report.md +1 -1
  138. package/skills/torusguard/payload/workflows/status.md +1 -1
  139. package/skills/torusguard/payload/workflows/verify.md +1 -1
  140. package/skills/torusguard/payload/workflows/web-validate.md +1 -1
  141. package/skills/torusguard-apply/SKILL.md +1 -1
  142. package/skills/torusguard-audit/SKILL.md +1 -1
  143. package/skills/torusguard-authorize/SKILL.md +1 -1
  144. package/skills/torusguard-exploit-check/SKILL.md +1 -1
  145. package/skills/torusguard-full/SKILL.md +1 -1
  146. package/skills/torusguard-harden/SKILL.md +1 -1
  147. package/skills/torusguard-init/SKILL.md +1 -1
  148. package/skills/torusguard-recheck/SKILL.md +1 -1
  149. package/skills/torusguard-report/SKILL.md +40 -23
  150. package/skills/torusguard-status/SKILL.md +1 -1
  151. package/skills/torusguard-verify/SKILL.md +1 -1
  152. package/skills/torusguard-web-validate/SKILL.md +1 -1
package/README.md CHANGED
@@ -9,10 +9,10 @@
9
9
  <strong>Zero Telemetry · Zero External Python Dependencies · Pure Standard-Library Architecture · 100% Local-First</strong>
10
10
  </p>
11
11
 
12
- [![npm version](https://img.shields.io/badge/npm-v1.3.5-cb3837.svg?style=flat-square&logo=npm)](https://www.npmjs.com/package/torusguard)
13
- [![GitHub Packages](https://img.shields.io/badge/GitHub%20Packages-v1.3.5-181717.svg?style=flat-square&logo=github)](https://github.com/githubmofo/TorusGuard/pkgs/npm/torusguard)
14
- [![Release](https://img.shields.io/badge/Release-v1.3.5-blue.svg?style=flat-square)](https://github.com/githubmofo/TorusGuard/releases/latest)
15
- [![Tests](https://img.shields.io/badge/Tests-81%2F81%20Passing-brightgreen.svg?style=flat-square)](harness/runner.py)
12
+ [![npm version](https://img.shields.io/badge/npm-v1.3.6-cb3837.svg?style=flat-square&logo=npm)](https://www.npmjs.com/package/torusguard)
13
+ [![GitHub Packages](https://img.shields.io/badge/GitHub%20Packages-v1.3.6-181717.svg?style=flat-square&logo=github)](https://github.com/githubmofo/TorusGuard/pkgs/npm/torusguard)
14
+ [![Release](https://img.shields.io/badge/Release-v1.3.6-blue.svg?style=flat-square)](https://github.com/githubmofo/TorusGuard/releases/latest)
15
+ [![Tests](https://img.shields.io/badge/Tests-120%2F120%20Passing-brightgreen.svg?style=flat-square)](harness/runner.py)
16
16
  [![Security Health](https://img.shields.io/badge/Health%20Score-100%2F100%20Hardened-brightgreen.svg?style=flat-square)](security_report.md)
17
17
  [![Rules Catalog](https://img.shields.io/badge/Rules%20Catalog-74%20Rules%20%7C%2018%20Families-indigo.svg?style=flat-square)](rules/)
18
18
  [![Terminal Standard](https://img.shields.io/badge/Terminal-75--col%20Standard-informational.svg?style=flat-square)](.torusguard/scripts/term_ui.py)
@@ -72,7 +72,7 @@ flowchart LR
72
72
  10. [Visual HTML Dashboard & SARIF v2.1.0 Export](#-visual-html-dashboard--sarif-v210-export)
73
73
  11. [AI Editor Guardrails Auto-Sync](#-ai-editor-guardrails-auto-sync)
74
74
  12. [Monorepo Fleet Support & Git Pre-Commit Diff Guard](#-monorepo-fleet-support--git-pre-commit-diff-guard)
75
- 13. [Verification & Test Harness (81/81 Passing Harness Explained)](#-verification--test-harness)
75
+ 13. [Verification & Test Harness (120/120 Passing Harness Explained)](#-verification--test-harness)
76
76
  14. [Security Policy & Responsible Disclosure](#-security-policy--responsible-disclosure)
77
77
  15. [License](#-license)
78
78
 
@@ -136,7 +136,7 @@ flowchart TD
136
136
 
137
137
  ## ⚔️ Why TorusGuard?
138
138
 
139
- | Security Dimension | Traditional SAST (SonarQube, Snyk) | Raw AI Coding Agents | TorusGuard v1.3.5 Engine |
139
+ | Security Dimension | Traditional SAST (SonarQube, Snyk) | Raw AI Coding Agents | TorusGuard v1.3.6 Engine |
140
140
  |:---|:---:|:---:|:---:|
141
141
  | **Target Architecture** | Human-written legacy codebases | High-churn AI code generation | **AI-built full-stack applications** |
142
142
  | **Remediation Model** | PDF reports & Jira tickets | Destructive full-file rewrites | **Ponytail Protocol** ($\le 35$ add, $\le 25$ del) |
@@ -426,7 +426,13 @@ TorusGuard automatically discovers and profiles multi-package workspaces:
426
426
  ## 🧪 Verification & Test Harness
427
427
 
428
428
  ### What Happens When You Run `npm test`?
429
- TorusGuard enforces a strict **100% pass requirement across 81 test suites** before every release.
429
+ TorusGuard enforces a strict **100% pass requirement across 120 test suites** before every release.
430
+ The test harness runs with **zero third-party dependencies** via standard Python 3:
431
+
432
+ ```bash
433
+ npm test
434
+ # Equivalent to: python harness/runner.py
435
+ ```
430
436
 
431
437
  When a developer runs:
432
438
  ```bash
@@ -447,7 +453,7 @@ npm test
447
453
 
448
454
  # Expected Output:
449
455
  # ================================================================================
450
- # SUMMARY: 81 Passed | 0 Failed
456
+ # SUMMARY: 120 Passed | 0 Failed
451
457
  # ================================================================================
452
458
  ```
453
459
 
package/bin/torusguard.js CHANGED
@@ -151,7 +151,7 @@ function cardDivider(title = '', borderColor = CYAN, double = false) {
151
151
  return ` ${borderColor}${left}${h.repeat(71)}${right}${RESET}`;
152
152
  }
153
153
 
154
- function cardHeader(title, subtitle = '', version = 'v1.3.5', borderColor = CYAN) {
154
+ function cardHeader(title, subtitle = '', version = 'v1.3.6', borderColor = CYAN) {
155
155
  const top = ` ${borderColor}╭${'─'.repeat(71)}╮${RESET}`;
156
156
  const bottom = ` ${borderColor}╰${'─'.repeat(71)}╯${RESET}`;
157
157
  const empty = ` ${borderColor}│${' '.repeat(71)}│${RESET}`;
@@ -169,7 +169,7 @@ function cardHeader(title, subtitle = '', version = 'v1.3.5', borderColor = CYAN
169
169
 
170
170
  function printHelp() {
171
171
  console.log();
172
- console.log(cardHeader('🛡️ T O R U S G U A R D C L I', 'Autonomous Security Engine for AI-Built Applications', 'v1.3.5'));
172
+ console.log(cardHeader('🛡️ T O R U S G U A R D C L I', 'Autonomous Security Engine for AI-Built Applications', 'v1.3.6'));
173
173
  console.log(`\n ${BOLD}Usage:${RESET} ${GREEN}npx torusguard${RESET} ${WHITE}[command]${RESET} ${GRAY}[options]${RESET}\n`);
174
174
 
175
175
  console.log(cardBorderTop('Commands'));
@@ -189,6 +189,7 @@ function printHelp() {
189
189
  console.log(cardDivider('AI & Memory Subcommands'));
190
190
  console.log(formatBoxLine(`${WHITE}rules sync${RESET} ${DIM}[--format all|cursor|claude|agent|windsurf]${RESET}`));
191
191
  console.log(formatBoxLine(`${WHITE}report --html${RESET} ${DIM}[--out <path>] Self-contained visual HTML dashboard${RESET}`));
192
+ console.log(formatBoxLine(`${WHITE}report --sarif${RESET} ${DIM}[--out <path>] OASIS SARIF v2.1.0 GitHub Scanning log${RESET}`));
192
193
  console.log(formatBoxLine(`${WHITE}memory context${RESET} ${DIM}[--role auditor|remediator|reviewer] [--file <f>]${RESET}`));
193
194
  console.log(formatBoxLine(`${WHITE}memory hook${RESET} ${DIM}[install|uninstall] Git pre-commit regression hook${RESET}`));
194
195
  console.log(formatBoxLine(`${WHITE}memory learn${RESET} ${DIM}[--commits <range>] Ingest security commit fixes${RESET}`));
@@ -250,7 +251,7 @@ if (command === 'status') {
250
251
  }
251
252
 
252
253
  console.log();
253
- console.log(cardHeader('🛡️ TORUSGUARD SECURITY POSTURE', '', 'v1.3.5'));
254
+ console.log(cardHeader('🛡️ TORUSGUARD SECURITY POSTURE', '', 'v1.3.6'));
254
255
  console.log(`\n ${BOLD}▸ Workspace:${RESET} ${GREEN}${cwd}${RESET}`);
255
256
  console.log(` ${BOLD}▸ Governance:${RESET} ${GREEN}Full Local Governance (.torusguard/)${RESET}`);
256
257
  console.log(` ${BOLD}▸ Living Report:${RESET} ${CYAN}security_report.md${RESET}\n`);
@@ -450,34 +451,69 @@ if (command === 'audit') {
450
451
 
451
452
  // Subcommand: report
452
453
  if (command === 'report') {
453
- if (args.includes('--html') || args[1] === 'html') {
454
- const htmlScript = path.join(cwd, '.torusguard', 'scripts', 'html_reporter.py');
454
+ const wantHtml = args.includes('--html') || args[1] === 'html' || args.includes('--out');
455
+ const wantSarif = args.includes('--sarif') || (!wantHtml && args[1] !== 'html');
456
+
457
+ // Resolve target directory (supports --target and --root)
458
+ const rootIdx = args.indexOf('--root') !== -1 ? args.indexOf('--root') : args.indexOf('--target');
459
+ let targetRoot = cwd;
460
+ if (rootIdx !== -1 && args[rootIdx + 1]) {
461
+ targetRoot = path.resolve(cwd, args[rootIdx + 1]);
462
+ }
463
+
464
+ let exitCode = 0;
465
+
466
+ // 1. If SARIF export is requested
467
+ if (wantSarif) {
468
+ const sarifScript = path.join(targetRoot, '.torusguard', 'scripts', 'sarif_exporter.py');
469
+ const fallbackSarifScript = path.join(rootDir, '.torusguard', 'scripts', 'sarif_exporter.py');
470
+ const actualSarifScript = fs.existsSync(fallbackSarifScript) ? fallbackSarifScript : sarifScript;
471
+
472
+ const sarifArgs = [actualSarifScript, '--root', targetRoot];
473
+ const sarifOutIdx = args.indexOf('--sarif-out');
474
+ if (sarifOutIdx !== -1 && args[sarifOutIdx + 1]) {
475
+ sarifArgs.push('--output', args[sarifOutIdx + 1]);
476
+ } else if (!wantHtml) {
477
+ const outIdx = args.indexOf('--out');
478
+ if (outIdx !== -1 && args[outIdx + 1]) {
479
+ sarifArgs.push('--output', args[outIdx + 1]);
480
+ }
481
+ }
482
+ const runIdIdx = args.indexOf('--run');
483
+ if (runIdIdx !== -1 && args[runIdIdx + 1]) {
484
+ sarifArgs.push('--run-id', args[runIdIdx + 1]);
485
+ }
486
+
487
+ const proc = spawnSync(pythonCmd, sarifArgs, { stdio: 'inherit', cwd: targetRoot });
488
+ if (proc.status !== 0 && proc.status !== null) {
489
+ exitCode = proc.status;
490
+ }
491
+ }
492
+
493
+ // 2. If Visual HTML dashboard is requested
494
+ if (wantHtml) {
495
+ const htmlScript = path.join(targetRoot, '.torusguard', 'scripts', 'html_reporter.py');
455
496
  const fallbackHtmlScript = path.join(rootDir, '.torusguard', 'scripts', 'html_reporter.py');
456
497
  const actualHtmlScript = fs.existsSync(fallbackHtmlScript) ? fallbackHtmlScript : htmlScript;
457
498
 
458
- let pyArgs = [actualHtmlScript];
499
+ let pyArgs = [actualHtmlScript, '--root', targetRoot];
459
500
  const outIdx = args.indexOf('--out');
460
501
  if (outIdx !== -1 && args[outIdx + 1]) {
461
- pyArgs.push('--out', args[outIdx + 1]);
462
- }
463
- const rootIdx = args.indexOf('--root') !== -1 ? args.indexOf('--root') : args.indexOf('--target');
464
- if (rootIdx !== -1 && args[rootIdx + 1]) {
465
- pyArgs.push('--root', args[rootIdx + 1]);
502
+ pyArgs.push('--out', path.resolve(cwd, args[outIdx + 1]));
503
+ } else {
504
+ pyArgs.push('--out', path.join(targetRoot, 'report.html'));
466
505
  }
467
506
  if (args.includes('--json')) {
468
507
  pyArgs.push('--json');
469
508
  }
470
509
 
471
- const proc = spawnSync(pythonCmd, pyArgs, { stdio: 'inherit', cwd });
472
- process.exit(proc.status !== null ? proc.status : 0);
473
- } else {
474
- const sarifScript = path.join(cwd, '.torusguard', 'scripts', 'sarif_exporter.py');
475
- const fallbackSarifScript = path.join(rootDir, '.torusguard', 'scripts', 'sarif_exporter.py');
476
- const actualSarifScript = fs.existsSync(fallbackSarifScript) ? fallbackSarifScript : sarifScript;
477
-
478
- const proc = spawnSync(pythonCmd, [actualSarifScript, ...args.slice(1)], { stdio: 'inherit', cwd });
479
- process.exit(proc.status !== null ? proc.status : 0);
510
+ const proc = spawnSync(pythonCmd, pyArgs, { stdio: 'inherit', cwd: targetRoot });
511
+ if (proc.status !== 0 && proc.status !== null) {
512
+ exitCode = proc.status;
513
+ }
480
514
  }
515
+
516
+ process.exit(exitCode);
481
517
  }
482
518
 
483
519
  // Subcommand: harden
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torusguard",
3
- "version": "1.3.5",
3
+ "version": "1.3.6",
4
4
  "description": "Security guardrails, governed remediation, and authorized runtime validation for AI-built web applications.",
5
5
  "main": "bin/torusguard.js",
6
6
  "bin": {
@@ -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, living security_report.md ground-truth ledger, 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
@@ -348,13 +348,18 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
348
348
  "cards": []
349
349
  }, indent=2), encoding="utf-8")
350
350
 
351
- # Ensure target project root .gitignore excludes .torusguard/memory/
351
+ # Ensure target project root .gitignore excludes .torusguard/memory/ and report.html
352
352
  root_gitignore = target_root / ".gitignore"
353
353
  if root_gitignore.exists():
354
354
  try:
355
355
  gi_content = root_gitignore.read_text(encoding="utf-8")
356
+ to_add = []
356
357
  if ".torusguard/memory" not in gi_content:
357
- root_gitignore.write_text(gi_content.rstrip() + "\n\n# TorusGuard security memory (local only)\n.torusguard/memory/\n", encoding="utf-8")
358
+ to_add.append(".torusguard/memory/")
359
+ if "report.html" not in gi_content:
360
+ to_add.append("report.html")
361
+ if to_add:
362
+ root_gitignore.write_text(gi_content.rstrip() + "\n\n# TorusGuard local artifacts\n" + "\n".join(to_add) + "\n", encoding="utf-8")
358
363
  except Exception:
359
364
  pass
360
365
 
@@ -142,25 +142,25 @@
142
142
  "schemas/remediation.schema.json": "544904239f871dec9552973e01e09dc1f40dbb8330f20d98c319f3b24031d630",
143
143
  "schemas/retest.schema.json": "97c0407ca4365a524020c430912f686f698cc0de90043194621071e9fc681cc7",
144
144
  "schemas/runtime-evidence.schema.json": "929d2b094c1cd1f7f9db07be1eba5994e8002477eab3fd24140e1e973fd18cc1",
145
- "scripts/apply_runner.py": "3863c894d0a57f4a71206dca802b26755f361958f085b4636f112350bde221a2",
146
- "scripts/audit_runner.py": "bdf4784ebec526a6f980879ce80aa7693ad2a8268fd4fa0334130ac3c1a7b22a",
145
+ "scripts/apply_runner.py": "f9c5374ea213b77069293e45ed3d878d7f3f0e31497c55bc97885efc14bfa57c",
146
+ "scripts/audit_runner.py": "98a3975ff79f8ffb0343d5606dd84a603fd35d741e2def6d70f83bc1ee8f01ff",
147
147
  "scripts/diff_guard.py": "0dc178cdde1ac0ae1a1ea4b2eb2ce1756b2126f6156909cf55d85249f115fcbd",
148
148
  "scripts/finding_scorer.py": "a5315be6ee256c01c4539da3d1905ebc8d0840a356b83c55f9f6f2654a9f0c60",
149
- "scripts/harden_runner.py": "c7a8074eaa9f6ebe61a17c553fd07bb543efcb1d5b4e01f24fd856367c048a70",
150
- "scripts/html_reporter.py": "30982f279b501834009159d7142624c973f36f2517b884a0ce4868d7ca42d1f3",
149
+ "scripts/harden_runner.py": "f6f6922f2ade98b40f3de3e211459c62483e8aa274cbe4515dbd0d308956e6b4",
150
+ "scripts/html_reporter.py": "e9901a1dbeddd7b1dccd04afc9005d64954ccc1f14ba6ec4bdb4aa0ea8c2c66c",
151
151
  "scripts/manifest_builder.py": "c0137927789a9e40a08243e630ac3c6990beb1b87807934e98906c8ad0b99a97",
152
152
  "scripts/memory_engine.py": "b715d0ca030e95eb06ad6eda99027535df8a7e37d64897c023be6a291cf13dc6",
153
153
  "scripts/monorepo_detector.py": "5603674136a5294ebfff89efeca0a546dd4a7deb1d184a2592ff21aff2131f73",
154
- "scripts/recheck_runner.py": "0c51d91b37bd3babf228b4b12b0e9d65953c8eae2e2e46596a1d42af8d057f71",
155
- "scripts/recipes_runner.py": "cd9ffba5fed53057aac56241dcbfda1e68248f323e51bbde3fe711634b099600",
156
- "scripts/report_sync.py": "278666954207a9eef1d479872546b99c16a8ded46bd3238ac9a09e2856b69813",
154
+ "scripts/recheck_runner.py": "dd6f35c98f6fd3d41d641bca419bb90739551c4900724a65447882b6d7dd4f54",
155
+ "scripts/recipes_runner.py": "6e057860e7d0e3b612a5b444b577255c9b7009b5dce0352098ab7d6c8c6659e7",
156
+ "scripts/report_sync.py": "c5f37c69e2e074c8ffd5953811907cf7c95e4c56f406ea16f3b5b9d878cfb774",
157
157
  "scripts/rules_sync.py": "4101b2ca8036ff4f468800b32a8d08898e8640a74d14124af53d454706a62d3a",
158
158
  "scripts/run_manager.py": "b738ff70879e46547d32fac6befc61de9599f676411384280fb9819ea3ad7035",
159
159
  "scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
160
- "scripts/sarif_exporter.py": "f060cfaf91dfb6b8e9c4036e354704204dfa8054720501f0ce2fadae0fb89540",
161
- "scripts/stack_detect.py": "3f755d9353d5a8fd33a25486d6af0101a1d1b0c2f70f5a28bb2af2fe6050adc2",
162
- "scripts/term_ui.py": "4870714add208f3da53c76a1250b1ceb8c104c0b708384e73427210dd0b50e6a",
163
- "skills/torusguard/SKILL.md": "3e63aaa90f5453ba2b7ea79ed6afbd64985fb083d198a34d552857abb2f183f4",
160
+ "scripts/sarif_exporter.py": "86700765212adb3ab590ca72614bf3ad4ce7ce60e3193f7f3bd1a04d34d10f6e",
161
+ "scripts/stack_detect.py": "c05a1ade4c8692025476bf7ea080a8f07c92e5d8e9a04f94c1654386352ffbdc",
162
+ "scripts/term_ui.py": "ca69398f85c86fe89526d6334b3ee866c890273997351113c3cc1765b7bd20c3",
163
+ "skills/torusguard/SKILL.md": "4d5b8e43fa3c09e5e1079cbc3e2184654219a2c47b2272db394da749969318f8",
164
164
  "skills/torusguard/bootstrap.py": "3d946f388cb4befa739c9d3b1404255d9a8ea5770ebbb79e5a1b9839589e9bc7",
165
165
  "skills/torusguard/references/auth-and-sessions.md": "c3e4b9600cb53fc28c993922dc880accbec5783ac90d5ee98d63b52762d19525",
166
166
  "skills/torusguard/references/business-logic-and-abuse.md": "58e87df2864d468af70c1ff39f5d540c687fa846b671457f85046ab2065fe99c",
@@ -190,32 +190,32 @@
190
190
  "skills/torusguard/references/ssrf-and-outbound-requests.md": "5ce59ebada2f227b3e0a27f612b59a47801c152d24d2d4d533bee435f32b1b05",
191
191
  "skills/torusguard/references/webhook-security.md": "8fd27cce1562a3dfda8d4fae29bef7cfd47a65c1e89c6868cdbcac161ccd2be8",
192
192
  "skills/torusguard/references/websocket-security.md": "b5315e49432184c006664436d689d426b7322fc6fbbba2899a9ea5e5bab74c92",
193
- "skills/torusguard-apply/SKILL.md": "453e1099ce3ae2184ae7bba34156cdafc6437976283e3839bef1c014bbc4bd9a",
194
- "skills/torusguard-audit/SKILL.md": "b8e2d0058bce604a00fee93055112b3872290373e8b90d95b3414ce2c33bf9d9",
195
- "skills/torusguard-authorize/SKILL.md": "67051f2db03f1957a63c10e6d39c963561c9c93f2c0c2e3289e936fe85b70da5",
196
- "skills/torusguard-exploit-check/SKILL.md": "7b040abfc10e6aedd56a432247b5c36c4872966b2bf363e56c5ae393db825e23",
197
- "skills/torusguard-full/SKILL.md": "f225de0e29d46f96fc0735e310394313dfecc987be430af14504498fc90847de",
198
- "skills/torusguard-harden/SKILL.md": "11039ce21f6990d7b15c176e0aefb5ee6d7631ab083391e3442c1020d5cae956",
199
- "skills/torusguard-init/SKILL.md": "89518de3585f4016b1e2ff6400979dcd7362c4b4f93fbdabd72e3ff4a59ba4d5",
200
- "skills/torusguard-recheck/SKILL.md": "d839251dbe5571769da0d4ae3ff2ef18533ee96f87bf460b44bb51279866be22",
201
- "skills/torusguard-report/SKILL.md": "f361f2e61141a4d0cea891da827146c3fce42b8b55c81d60d0ac999312e4d6cd",
202
- "skills/torusguard-status/SKILL.md": "e14ab6276207bf4921749ec38a4c4b0bf482e84010a4e1b7c2b6f8ce7804f047",
203
- "skills/torusguard-verify/SKILL.md": "f9aff4ca514e72883ac630245b6f3b62e035a9e54bdbe69ae8edb59bd9153691",
204
- "skills/torusguard-web-validate/SKILL.md": "006d638d9d6f7ee5f9eb880704955f01eff1c3b9bb3baa8ac900fd807f6f589a",
193
+ "skills/torusguard-apply/SKILL.md": "4cdd01d8159fc5f7519a806526a119e6d67e41b8af195de018b05d6af09acb12",
194
+ "skills/torusguard-audit/SKILL.md": "0065336b125cfa8ec766dcec585bce4bbac66b3b063c174b7183dffef18e090d",
195
+ "skills/torusguard-authorize/SKILL.md": "8694e6cef71cbeb6605fed33dd1f24b74352541069e54de7c3f48c9676e9aa3a",
196
+ "skills/torusguard-exploit-check/SKILL.md": "87e0e01f28f3efea8dbe81790abaceb845a1290c75a6a16bbd256251cd0539a9",
197
+ "skills/torusguard-full/SKILL.md": "35f8b38b08fef5a09504312ef3e54921b1f8f31f197bbe2af1474bcce2e83e1c",
198
+ "skills/torusguard-harden/SKILL.md": "4332761e5454a504176eebbba2d4c585bcf066c8046c014cebc0f5771379c089",
199
+ "skills/torusguard-init/SKILL.md": "03e599a5dad4262396e6b1a75859f76739b0b1480d8cc64544296106da903dfc",
200
+ "skills/torusguard-recheck/SKILL.md": "72a0a79b29dcc7f7ae054f00c53e005bc92778f2c6bf3ad828f6391e859d9c1c",
201
+ "skills/torusguard-report/SKILL.md": "6dc62fb2c9e2986827a802b7cabf41ce41d00a47573524a4bf1642a8d8e2249e",
202
+ "skills/torusguard-status/SKILL.md": "2ad72e5d317e1d6fe0606f6926b1721dc01ba98b5daa2bfaa90bdd953a67bdf7",
203
+ "skills/torusguard-verify/SKILL.md": "810c31ba9adc1b410b22eb8503f266be2d51e260a9c6828fd2938e2774e5baa7",
204
+ "skills/torusguard-web-validate/SKILL.md": "3e02d9734402e8fbc86a0b5c2fdac945ef4fc9d60ba1b992197b1373427ad16e",
205
205
  "templates/audit-report.template.md": "71149dd05b01a74287a47781fdc71fd2d1b4b70337da303bf78767d0410a6c90",
206
206
  "templates/authorization.template.md": "81ef843d42a19412c369f383b787465ac24173c0b14c1f5f211786eab3d10e8b",
207
207
  "templates/finding-card.template.md": "8f756edbd3e4139d3da2fb96f35bd2d2b267b33b754f187b590a89584265c1e6",
208
208
  "templates/remediation-bundle.template.md": "4d85a540e3a2e74f9b21fc8a2a1072e27ca03e97cd67ca482f529cfe722acc4d",
209
- "workflows/apply.md": "fde7e879db5879bc6c8e67b5bd40473065688bba91149a01f66ad4739f4c8443",
210
- "workflows/audit.md": "b02a7d2536c81b35ab4519b7f9eda3396d08f09da581ef299dc8fed83b4c082d",
211
- "workflows/authorize.md": "71b14c2ffa24b1ad511d019a7da86854bf1bf94c282f563e05e9ad3b8493e8ca",
212
- "workflows/exploit-check.md": "01c0a51e4b12a9dbb1d4f2b28d0bb495d92f95b786f5f1df59467b8fc6c61855",
213
- "workflows/harden.md": "e68a78c47a2c4ec1d65adb08104d2fa16eb0c4530cf9b78400fd147f2076fb95",
214
- "workflows/init.md": "f71438745a7e8d59dcf2e1089f7c5ccf2340e7909e56e1257b24c8ca79353162",
215
- "workflows/memory.md": "faf93f39917fb6d0da23f9794e8337e643fd0a240cc46ca702fef84e02f5b867",
216
- "workflows/recheck.md": "426a719a9c4233a653daa8fe0265370492f3a17a422517f7930549c991d25c93",
217
- "workflows/report.md": "2aad2cbf2ffc781355e1186bb28a29b3da5efbacc57c8f44c9976aa635f0b120",
218
- "workflows/status.md": "f3445bbf90402df819472180d5ae251a17b4f491ea3402d74f134bf55c2bf570",
219
- "workflows/verify.md": "48f37892d329287059492ffaebf7022253fd5515a0a1a3253799e5cea765a21a",
220
- "workflows/web-validate.md": "4d81294432e4d06e6c21db9a517b7cf1052744df3d821ed947a7751acb4fe39f"
209
+ "workflows/apply.md": "8dd37fecc44e2820e82c29e2c6b2970936734ed5102d36950889a9eb8b19dbab",
210
+ "workflows/audit.md": "7e78ebb885176d65e86ed45a90a4326b942d484c2b5c8bff1d7bda141790de2f",
211
+ "workflows/authorize.md": "28ca58cfc656e956f7cec8160f2aadc152abcde3eb5ad5588df149007afb0df8",
212
+ "workflows/exploit-check.md": "41e77afe912be9266c5bc1e00fd796baff22a67973eb6e86d196d34f4d7bdfa4",
213
+ "workflows/harden.md": "24c62ea0233bf5cb21308497869790fa6f24b6cbb563fd2ebf858ff02b09bba9",
214
+ "workflows/init.md": "9a9aeaff6bd2217323ad72fb4043f46057deaa45eb3380f679d9aef3d36bfc8b",
215
+ "workflows/memory.md": "8ad2ec154176e2540c2859a28eff9f7c2dbca0217aa29d0f4aa88b87c43f8bef",
216
+ "workflows/recheck.md": "42eecc3ba194564d48a6a88d8003e86cafe003503e887dc565314d4aa558e8fd",
217
+ "workflows/report.md": "b98652ee0552b7bb73eeb78dc80d2b0a108cc505523cbd1b3ada6064409e4629",
218
+ "workflows/status.md": "dfbc2b75ba45ff70b60522addca4032a667241364b0907cd77a43bf9271dfa56",
219
+ "workflows/verify.md": "6412e123a9346240e5ba898a0da73d3409d9a215d6e8f202ab2eb5719b663731",
220
+ "workflows/web-validate.md": "3b2a3d02b69469539b4a48ed3bd355362927cc21470dbcdeccba564a9e68a371"
221
221
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- TorusGuard Governed Patch Application & Snapshot Engine (v1.3.5)
3
+ TorusGuard Governed Patch Application & Snapshot Engine (v1.3.6)
4
4
  Interactive Human Gate authorization, pre-apply .bak rollback snapshots,
5
5
  atomic patch application, and Golden Fix Recipe distillation into persistent memory.
6
6
  Strict 75-column terminal UI formatting.
@@ -58,7 +58,7 @@ def box_line(content: str, width: int = 67, border: str = "│", border_color: s
58
58
  return term_ui.format_box_line(content, width=width, border=border, border_color=border_color)
59
59
  return f" {border_color}{border}{RESET} {content}"
60
60
 
61
- def box_header(title: str, subtitle: str = "", version: str = "v1.3.5", border_color: str = CYAN) -> str:
61
+ def box_header(title: str, subtitle: str = "", version: str = "v1.3.6", border_color: str = CYAN) -> str:
62
62
  if term_ui:
63
63
  return term_ui.card_header(title, subtitle, version, border_color)
64
64
  return f"=== {title} ({version}) ==="
@@ -108,8 +108,14 @@ def execute_rollback(target_root: Path, run_id_arg: Optional[str] = None) -> Non
108
108
  shutil.copy2(bak_file, dest_file)
109
109
  restored_files.append(orig_rel)
110
110
 
111
+ try:
112
+ import report_sync
113
+ report_sync.record_rollback_results(target_root, restored_files, snapshot_dir.name)
114
+ except Exception:
115
+ pass
116
+
111
117
  print()
112
- print(box_header("🛡️ TORUSGUARD ROLLBACK RESTORATION", "Restored original files from pre-apply snapshot", "v1.3.5"))
118
+ print(box_header("🛡️ TORUSGUARD ROLLBACK RESTORATION", "Restored original files from pre-apply snapshot", "v1.3.6"))
113
119
  print()
114
120
 
115
121
  print(border_top("Rollback Snapshot Restored"))
@@ -138,7 +144,7 @@ def execute_apply(target_root: Path, run_id_arg: Optional[str] = None, auto_appr
138
144
  bundle_meta_files = list(bundles_dir.glob("*/metadata.json")) if bundles_dir.is_dir() else []
139
145
  if not bundle_meta_files:
140
146
  print()
141
- print(box_header("🛡️ TORUSGUARD GOVERNED PATCH APPLIER", "Human-Gate Authorization, Snapshots & Golden Recipe Distillation", "v1.3.5"))
147
+ print(box_header("🛡️ TORUSGUARD GOVERNED PATCH APPLIER", "Human-Gate Authorization, Snapshots & Golden Recipe Distillation", "v1.3.6"))
142
148
  print()
143
149
  print(f" {YELLOW}ℹ Zero candidate remediation bundles found in run: {run_folder.name}{RESET}")
144
150
  print(f" {GRAY}The findings in this run require manual review or AI-assisted remediation.{RESET}\n")
@@ -163,7 +169,7 @@ def execute_apply(target_root: Path, run_id_arg: Optional[str] = None, auto_appr
163
169
 
164
170
  # Header Card
165
171
  print()
166
- print(box_header("🛡️ TORUSGUARD GOVERNED PATCH APPLIER", "Human-Gate Authorization, Snapshots & Golden Recipe Distillation", "v1.3.5"))
172
+ print(box_header("🛡️ TORUSGUARD GOVERNED PATCH APPLIER", "Human-Gate Authorization, Snapshots & Golden Recipe Distillation", "v1.3.6"))
167
173
  print()
168
174
 
169
175
  print(border_top("Candidate Bundles Ready for Application"))