torusguard 2.1.2 → 2.1.3

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.
@@ -9,7 +9,7 @@
9
9
  "agents/validator.md": "79fc4431de5c5507f8730aee6c5c3e61fd238cbf8cf8c7c6aac462eee9761ed6",
10
10
  "config/scope.json": "b198a86186b4c6d5e1af516bf4e3a6afa8878e622ca1d57a5bf72d294f8c6f25",
11
11
  "config/slash-commands.json": "305c1dc5b556e8d64ad9dd585dafac1a9955cf1bd5321429955b19b7a62736b6",
12
- "config/torusguard.json": "55dbde335997421a01c97709fd1672ad70fa921bfe8346dd57552b799db2419e",
12
+ "config/torusguard.json": "e8e41f3be04a06deb32ce5faaa93ddd608abfb2694b30325cac5085f3bfec9d8",
13
13
  "core/__init__.py": "2120562452ae03c84468d67246dc93376f7ebcde8e4ca767c6253bc92c35dbbf",
14
14
  "core/agent_roles.py": "d7189dbf1d3ae4e330eb316bed5d399a18992295addf466f4c6552bc14ae6a34",
15
15
  "core/ast_walker.py": "309564d168e6eb9e3e93aceb29a95a61872b35a4da7235ee49e79e9d3a5e7cc6",
@@ -216,9 +216,9 @@
216
216
  "scripts/sarif_exporter.py": "86700765212adb3ab590ca72614bf3ad4ce7ce60e3193f7f3bd1a04d34d10f6e",
217
217
  "scripts/skill_profiler.py": "ada83e022795febb2365a73753656ff881993d77cf73517e818d668e961adb45",
218
218
  "scripts/stack_detect.py": "c05a1ade4c8692025476bf7ea080a8f07c92e5d8e9a04f94c1654386352ffbdc",
219
- "scripts/status_runner.py": "4c358c91950c7874bcc6a5f23f2d3fda62b0752efcf6c6b658adf02ed77c7752",
219
+ "scripts/status_runner.py": "a7421e25e2e34c1b83960ad117f5ea23d6f08b8af8b664be3fe03f70a3962db3",
220
220
  "scripts/stride_generator.py": "c7a4ea2a19a7386dfc6c0fb301e933a32de2c8963ffa605e5aaa651cf880507f",
221
- "scripts/term_ui.py": "ca69398f85c86fe89526d6334b3ee866c890273997351113c3cc1765b7bd20c3",
221
+ "scripts/term_ui.py": "a23435c703c4e8b68c5b80a539d59de2eda1cb01b0d9c47909ba72efde3be29b",
222
222
  "skills/torusguard/SKILL.md": "15c69cb10eca1a10344b494888dce57e2baf227c3282bd54424a36ce35fb2460",
223
223
  "skills/torusguard/bootstrap.py": "f7ce48cc310dcdbf86c028f05a8f5ad22677f4cebb1bec5c90d173a9044342c5",
224
224
  "skills/torusguard/references/auth-and-sessions.md": "c3e4b9600cb53fc28c993922dc880accbec5783ac90d5ee98d63b52762d19525",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "../schemas/torusguard-config.schema.json",
3
- "version": "1.0.0",
3
+ "version": "2.1.3",
4
4
  "product": "TorusGuard Security Skill Kit",
5
5
  "severity_threshold": "medium",
6
6
  "auto_detect_stack": true,
@@ -58,7 +58,7 @@ def collect_status(target_dir: Path) -> WorkspaceStatus:
58
58
  is_init = tg_dir.is_dir()
59
59
 
60
60
  # 1. Read config
61
- version = "1.4.0"
61
+ version = "2.1.3"
62
62
  stack_name = "Undetected"
63
63
  cfg_file = tg_dir / "config" / "torusguard.json"
64
64
  if cfg_file.is_file():
@@ -94,7 +94,7 @@ def collect_status(target_dir: Path) -> WorkspaceStatus:
94
94
  if rules_root.is_dir():
95
95
  active_rules_count = sum(1 for f in rules_root.rglob("TG-*.md"))
96
96
  if active_rules_count == 0:
97
- active_rules_count = 74 # Canonical rule catalog default
97
+ active_rules_count = 88 # Canonical rule catalog default
98
98
 
99
99
  # 3. Read run history
100
100
  total_runs = 0
@@ -210,7 +210,7 @@ def print_status_card(status: WorkspaceStatus) -> None:
210
210
  print(format_box_line(f"Workspace: {WHITE}{status.target_path}{RESET}", 67))
211
211
  print(format_box_line(f"Status: {init_str}", 67))
212
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))
213
+ print(format_box_line(f"Active Rules: {GREEN}{status.active_rules_count}{RESET} canonical rules enabled across 22 families", 67))
214
214
  print(card_border_bottom(CYAN))
215
215
  print()
216
216
 
@@ -143,7 +143,7 @@ def card_divider(title: str = "", border_color: str = CYAN, double: bool = False
143
143
  return f" {border_color}{left}{h} {BOLD}{WHITE}{title}{RESET}{border_color} {h * rem}{right}{RESET}"
144
144
  return f" {border_color}{left}{h * 71}{right}{RESET}"
145
145
 
146
- def card_header(title: str, subtitle: str = "", version: str = "v1.3.4", border_color: str = CYAN) -> str:
146
+ def card_header(title: str, subtitle: str = "", version: str = "v2.1.3", border_color: str = CYAN) -> str:
147
147
  """Generate standardized 75-column curved header box."""
148
148
  top = f" {border_color}╭{'─' * 71}╮{RESET}"
149
149
  bottom = f" {border_color}╰{'─' * 71}╯{RESET}"
package/README.md CHANGED
@@ -11,8 +11,8 @@
11
11
 
12
12
  <p align="center">
13
13
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
14
- <a href="https://github.com/githubmofo/TorusGuard/releases"><img src="https://img.shields.io/badge/version-v2.1.2-orange.svg" alt="Version"></a>
15
- <a href="https://www.npmjs.com/package/torusguard"><img src="https://img.shields.io/badge/npm-v2.1.2-CB3837?logo=npm&logoColor=white" alt="npm: v2.1.2"></a>
14
+ <a href="https://github.com/githubmofo/TorusGuard/releases"><img src="https://img.shields.io/badge/version-v2.1.3-orange.svg" alt="Version"></a>
15
+ <a href="https://www.npmjs.com/package/torusguard"><img src="https://img.shields.io/badge/npm-v2.1.3-CB3837?logo=npm&logoColor=white" alt="npm: v2.1.3"></a>
16
16
  <img src="https://img.shields.io/badge/Privacy-Local_First-success" alt="Privacy: Local First">
17
17
  <img src="https://img.shields.io/badge/Dependencies-Zero-brightgreen" alt="Dependencies: Zero">
18
18
  <img src="https://img.shields.io/badge/SARIF-v2.1.0-6C3483" alt="SARIF">
@@ -276,24 +276,55 @@ flowchart TD
276
276
 
277
277
  ---
278
278
 
279
- ## 🚀 Installation
279
+ ## 🚀 Installation & How to Use (3 Options)
280
+
281
+ TorusGuard can be run without installation via `npx`, installed globally or locally via `npm`, compiled from source with `go build`, or installed via `go install`.
282
+
283
+ | Option | Method | Best For | Dedicated Guide |
284
+ | :--- | :--- | :--- | :--- |
285
+ | **Option 1** | **npm & npx** | Node.js developers, zero-install CLI, CI/CD | 📖 [Option 1 Guide](docs/usage/option-1-npm.md) |
286
+ | **Option 2** | **Build from Source** | Contributors, custom rules, Go development | 📖 [Option 2 Guide](docs/usage/option-2-source.md) |
287
+ | **Option 3** | **Go Install** | Go projects, single-binary, zero Node.js/npm | 📖 [Option 3 Guide](docs/usage/option-3-go-install.md) |
288
+
289
+ ---
280
290
 
281
291
  ### Option 1: npm (Primary)
282
292
 
293
+ #### Method A: Direct NPX Zero-Install (Recommended)
294
+ Run directly without installing any packages globally or locally:
295
+
283
296
  ```bash
284
- npm install -g torusguard
297
+ npx torusguard init
285
298
  ```
286
299
 
287
- Or use directly without installing:
300
+ *Tip: Use `npx torusguard@latest init` to guarantee the freshest release.*
288
301
 
302
+ #### Method B: Global Installation
289
303
  ```bash
290
- npx torusguard init
304
+ npm install -g torusguard
305
+ torusguard init
306
+ ```
307
+
308
+ #### Method C: Local Project Installation
309
+ ```bash
310
+ npm install -D torusguard
291
311
  ```
292
312
 
313
+ > 💡 **Using TorusGuard after `npm install torusguard`:**
314
+ > TorusGuard is a CLI security engine, not an importable JavaScript library. When installed locally, the binary resides in `node_modules/.bin/torusguard`.
315
+ > You can run it via:
316
+ > - `npx torusguard init` *(npx automatically uses your local `node_modules` binary)*
317
+ > - Adding `"security:audit": "torusguard audit"` to your `package.json` scripts (`npm run security:audit`)
318
+ > - Direct path: `./node_modules/.bin/torusguard audit`
319
+
293
320
  <a href="https://www.npmjs.com/package/torusguard">
294
- <img src="https://img.shields.io/badge/npm-v2.1.2-CB3837?logo=npm&logoColor=white" alt="npm package">
321
+ <img src="https://img.shields.io/badge/npm-v2.1.3-CB3837?logo=npm&logoColor=white" alt="npm package">
295
322
  </a>
296
323
 
324
+ 👉 **[Read the Full Option 1 (npm & npx) Dedicated Guide →](docs/usage/option-1-npm.md)**
325
+
326
+ ---
327
+
297
328
  ### Option 2: Build from Source (Recommended for Contributors)
298
329
 
299
330
  ```bash
@@ -302,12 +333,37 @@ cd TorusGuard
302
333
  go build -o torusguard ./cmd/torusguard
303
334
  ```
304
335
 
336
+ On Windows:
337
+ ```powershell
338
+ go build -o torusguard.exe ./cmd/torusguard
339
+ ```
340
+
341
+ Run directly:
342
+ ```bash
343
+ ./torusguard init
344
+ ./torusguard audit
345
+ ```
346
+
347
+ 👉 **[Read the Full Option 2 (Build from Source) Dedicated Guide →](docs/usage/option-2-source.md)**
348
+
349
+ ---
350
+
305
351
  ### Option 3: Go Install
306
352
 
353
+ Install directly into `$GOPATH/bin`:
354
+
307
355
  ```bash
308
- go install github.com/torusguard/torusguard/cmd/torusguard@latest
356
+ go install github.com/githubmofo/TorusGuard/cmd/torusguard@latest
309
357
  ```
310
358
 
359
+ Verify and run:
360
+ ```bash
361
+ torusguard --version
362
+ torusguard init
363
+ ```
364
+
365
+ 👉 **[Read the Full Option 3 (Go Install) Dedicated Guide →](docs/usage/option-3-go-install.md)**
366
+
311
367
  ---
312
368
 
313
369
  ## 💻 Usage
package/bin/torusguard.js CHANGED
@@ -15,14 +15,15 @@ const command = args[0] || 'init';
15
15
  const rootDir = path.resolve(__dirname, '..');
16
16
  const cwd = process.cwd();
17
17
 
18
+ let PKG_VERSION = '2.1.3';
19
+ try {
20
+ const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf-8'));
21
+ PKG_VERSION = pkg.version || PKG_VERSION;
22
+ } catch (e) {}
23
+
18
24
  // Parse version flag immediately
19
25
  if (command === '--version' || command === '-v' || command === 'version') {
20
- let ver = '1.4.0';
21
- try {
22
- const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf-8'));
23
- ver = pkg.version || ver;
24
- } catch (e) {}
25
- console.log(`torusguard v${ver}`);
26
+ console.log(`torusguard v${PKG_VERSION}`);
26
27
  process.exit(0);
27
28
  }
28
29
 
@@ -196,7 +197,7 @@ function cardDivider(title = '', borderColor = CYAN, double = false) {
196
197
  return ` ${borderColor}${left}${h.repeat(71)}${right}${RESET}`;
197
198
  }
198
199
 
199
- function cardHeader(title, subtitle = '', version = 'v1.3.6', borderColor = CYAN) {
200
+ function cardHeader(title, subtitle = '', version = `v${PKG_VERSION}`, borderColor = CYAN) {
200
201
  const top = ` ${borderColor}╭${'─'.repeat(71)}╮${RESET}`;
201
202
  const bottom = ` ${borderColor}╰${'─'.repeat(71)}╯${RESET}`;
202
203
  const empty = ` ${borderColor}│${' '.repeat(71)}│${RESET}`;
@@ -214,7 +215,7 @@ function cardHeader(title, subtitle = '', version = 'v1.3.6', borderColor = CYAN
214
215
 
215
216
  function printHelp() {
216
217
  console.log();
217
- console.log(cardHeader('🛡️ T O R U S G U A R D C L I', 'Autonomous Security Engine for AI-Built Applications', 'v1.4.0'));
218
+ console.log(cardHeader('🛡️ T O R U S G U A R D C L I', 'Autonomous Security Engine for AI-Built Applications', `v${PKG_VERSION}`));
218
219
  console.log(`\n ${BOLD}Usage:${RESET} ${GREEN}npx torusguard${RESET} ${WHITE}[command]${RESET} ${GRAY}[options]${RESET}\n`);
219
220
 
220
221
  console.log(cardBorderTop('Commands'));
@@ -309,7 +310,7 @@ if (command === 'status') {
309
310
  }
310
311
 
311
312
  console.log();
312
- console.log(cardHeader('🛡️ TORUSGUARD SECURITY POSTURE', '', 'v1.3.6'));
313
+ console.log(cardHeader('🛡️ TORUSGUARD SECURITY POSTURE', '', `v${PKG_VERSION}`));
313
314
  console.log(`\n ${BOLD}▸ Workspace:${RESET} ${GREEN}${cwd}${RESET}`);
314
315
  console.log(` ${BOLD}▸ Governance:${RESET} ${GREEN}Full Local Governance (.torusguard/)${RESET}`);
315
316
  console.log(` ${BOLD}▸ Living Report:${RESET} ${CYAN}security_report.md${RESET}\n`);
@@ -331,7 +332,7 @@ if (command === 'status') {
331
332
  console.log();
332
333
 
333
334
  console.log(cardBorderTop('Governance Telemetry'));
334
- console.log(formatBoxLine(`Rules Catalog: ${GREEN}74 Canonical Security Rules${RESET} (18 families)`));
335
+ console.log(formatBoxLine(`Rules Catalog: ${GREEN}88 Canonical Security Rules${RESET} (22 families)`));
335
336
  console.log(formatBoxLine(`Severity Floor: ${YELLOW}${cfg.severity_threshold || 'medium'}${RESET}`));
336
337
  console.log(formatBoxLine(`Runs Directory: ${DIM}${cfg.runs_dir || '.torusguard/runs'}${RESET}`));
337
338
  console.log(formatBoxLine(`Ponytail Bounds: ${GREEN}<= 35 additions, <= 25 deletions${RESET}`));
@@ -339,16 +340,18 @@ if (command === 'status') {
339
340
  console.log(cardBorderBottom());
340
341
  console.log();
341
342
 
342
- console.log(cardBorderTop('Rule Families (18 Families / 74 Rules)'));
343
- console.log(formatBoxLine(`${YELLOW}TG-SEC${RESET} Secrets (7) ${YELLOW}TG-DB${RESET} Database Safety (4)`));
344
- console.log(formatBoxLine(`${YELLOW}TG-INPUT${RESET} Input Validation (6) ${YELLOW}TG-AUTH${RESET} Authentication (8)`));
343
+ console.log(cardBorderTop('Rule Families (22 Families / 88 Rules)'));
344
+ console.log(formatBoxLine(`${YELLOW}TG-SEC${RESET} Secrets & Tokens (7) ${YELLOW}TG-AUTH${RESET} Authentication (8)`));
345
+ console.log(formatBoxLine(`${YELLOW}TG-DB${RESET} Database Isolation (4) ${YELLOW}TG-INPUT${RESET} Input & Traversal (8)`));
345
346
  console.log(formatBoxLine(`${YELLOW}TG-RATE${RESET} Rate Limiting (3) ${YELLOW}TG-AGENT${RESET} AI Agent Security (4)`));
346
- console.log(formatBoxLine(`${YELLOW}TG-SSRF${RESET} Server Request (4) ${YELLOW}TG-WEBHOOK${RESET} Webhook Trust (4)`));
347
- console.log(formatBoxLine(`${YELLOW}TG-WS${RESET} WebSocket (4) ${YELLOW}TG-CSRF${RESET} Cross-Site Request (2)`));
348
- console.log(formatBoxLine(`${YELLOW}TG-GQL${RESET} GraphQL Security (4) ${YELLOW}TG-SUPPLY${RESET} Supply Chain (6)`));
349
- console.log(formatBoxLine(`${YELLOW}TG-BIZ${RESET} Business Logic (4) ${YELLOW}TG-CACHE${RESET} Cache Isolation (3)`));
350
- console.log(formatBoxLine(`${YELLOW}TG-CLIENT${RESET} Client Bundles (2) ${YELLOW}TG-PLATFORM${RESET}Platform Config (4)`));
351
- console.log(formatBoxLine(`${YELLOW}TG-DIFF${RESET} Diff Inspection (3) ${YELLOW}TG-EDGE${RESET} Serverless / Edge (2)`));
347
+ console.log(formatBoxLine(`${YELLOW}TG-SSRF${RESET} Server-Side Request (4) ${YELLOW}TG-WEBHOOK${RESET} Webhook Signature (4)`));
348
+ console.log(formatBoxLine(`${YELLOW}TG-WS${RESET} WebSocket Safety (4) ${YELLOW}TG-CSRF${RESET} Cross-Site Request (2)`));
349
+ console.log(formatBoxLine(`${YELLOW}TG-GQL${RESET} GraphQL Introspection (4)${YELLOW}TG-SUPPLY${RESET} Supply Chain Health (6)`));
350
+ console.log(formatBoxLine(`${YELLOW}TG-BIZ${RESET} Business Logic (4) ${YELLOW}TG-CACHE${RESET} Cache Poisoning (3)`));
351
+ console.log(formatBoxLine(`${YELLOW}TG-CLIENT${RESET} Client Bundle Secrets (2)${YELLOW}TG-PLATFORM${RESET}Platform Hardening (4)`));
352
+ console.log(formatBoxLine(`${YELLOW}TG-DIFF${RESET} Polyglot Bypass Guard (3)${YELLOW}TG-EDGE${RESET} Edge & Serverless (2)`));
353
+ console.log(formatBoxLine(`${YELLOW}TG-CONT${RESET} Container Hardening (4) ${YELLOW}TG-GIT${RESET} Git Secret Mining (3)`));
354
+ console.log(formatBoxLine(`${YELLOW}TG-REDOS${RESET} ReDoS Complexity Guard (2)${YELLOW}TG-RAG${RESET} RAG & Vector Scoping (3)`));
352
355
  console.log(cardBorderBottom());
353
356
 
354
357
  console.log(`\n ${DIM}Quick Action:${RESET} In your AI chat, run ${CYAN}/torusguard-audit${RESET} to scan.\n`);
@@ -640,6 +643,9 @@ if (command === 'recipes') {
640
643
  if (command === 'init') {
641
644
  const { target, remaining } = parseTargetAndArgs(args);
642
645
  const targetDir = path.resolve(cwd, target);
646
+ if (!fs.existsSync(targetDir)) {
647
+ fs.mkdirSync(targetDir, { recursive: true });
648
+ }
643
649
  const localBootstrap = path.join(rootDir, 'skills', 'torusguard', 'bootstrap.py');
644
650
  const localInstall = path.join(rootDir, 'install.py');
645
651
  const scriptToRun = fs.existsSync(localBootstrap) ? localBootstrap : localInstall;
@@ -655,13 +661,7 @@ if (command === 'init') {
655
661
  // Subcommand: update
656
662
  if (command === 'update') {
657
663
  const https = require('https');
658
- const pkgJsonPath = path.join(rootDir, 'package.json');
659
- let currentVersion = '1.4.0';
660
- try {
661
- if (fs.existsSync(pkgJsonPath)) {
662
- currentVersion = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')).version || currentVersion;
663
- }
664
- } catch (e) {}
664
+ const currentVersion = PKG_VERSION;
665
665
 
666
666
  console.log();
667
667
  console.log(cardHeader('🛡️ TORUSGUARD UPDATE CHECK', 'Package Distribution & Registry Verifier', `v${currentVersion}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torusguard",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
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": {
@@ -15,6 +15,7 @@
15
15
  "LICENSE"
16
16
  ],
17
17
  "scripts": {
18
+ "postinstall": "node -e \"console.log('\\n🛡️ TorusGuard v2.1.3 installed! Run: npx torusguard init\\n')\"",
18
19
  "test": "python harness/runner.py",
19
20
  "init": "node bin/torusguard.js init",
20
21
  "status": "node bin/torusguard.js status",
@@ -144,7 +144,7 @@ def card_divider(title: str = "", border_color: str = CYAN, double: bool = False
144
144
  return f" {border_color}{left}{h} {BOLD}{WHITE}{title}{RESET}{border_color} {h * rem}{right}{RESET}"
145
145
  return f" {border_color}{left}{h * 71}{right}{RESET}"
146
146
 
147
- def card_header(title: str, subtitle: str = "", version: str = "v2.1.2", border_color: str = CYAN) -> str:
147
+ def card_header(title: str, subtitle: str = "", version: str = "v2.1.3", border_color: str = CYAN) -> str:
148
148
  """Generate standardized 75-column curved header box."""
149
149
  top = f" {border_color}╭{'─' * 71}╮{RESET}"
150
150
  bottom = f" {border_color}╰{'─' * 71}╯{RESET}"
@@ -164,7 +164,7 @@ def card_header(title: str, subtitle: str = "", version: str = "v2.1.2", border_
164
164
  def print_header():
165
165
  """Print the branded TorusGuard header card."""
166
166
  print()
167
- print(card_header("🛡️ T O R U S G U A R D", "Autonomous Security Engine for AI-Built Applications", version="v2.1.2"))
167
+ print(card_header("🛡️ T O R U S G U A R D", "Autonomous Security Engine for AI-Built Applications", version="v2.1.3"))
168
168
  print()
169
169
 
170
170
 
@@ -172,13 +172,13 @@ def print_step_1_assets(file_count):
172
172
  """Print the enhanced Step 1 asset unpacking card."""
173
173
  print(card_border_top("Step 1/3 ─── Unpacking Governance Assets"))
174
174
  print(card_line(""))
175
- print(card_line(f"{GREEN}✔{RESET} Canonical security rules {DIM}71 rules across 11 families{RESET}"))
175
+ print(card_line(f"{GREEN}✔{RESET} Canonical security rules {DIM}88 rules across 22 families{RESET}"))
176
176
  print(card_line(f"{GREEN}✔{RESET} JSON validation schemas {DIM}8 formal schemas{RESET}"))
177
177
  print(card_line(f"{GREEN}✔{RESET} Specialist agent specifications {DIM}5 isolated agents{RESET}"))
178
- print(card_line(f"{GREEN}✔{RESET} Workflow templates {DIM}11 slash commands{RESET}"))
179
- print(card_line(f"{GREEN}✔{RESET} Framework reference guides {DIM}10 security guides{RESET}"))
178
+ print(card_line(f"{GREEN}✔{RESET} Governed workflow templates {DIM}25 commands & 13 MCP tools{RESET}"))
179
+ print(card_line(f"{GREEN}✔{RESET} Framework reference guides {DIM}22 architectural guides{RESET}"))
180
180
  print(card_line(""))
181
- print(card_line(f"{BOLD}{WHITE}{file_count} files unpacked{RESET}"))
181
+ print(card_line(f"{BOLD}{WHITE}{file_count} files unpacked into .torusguard/{RESET}"))
182
182
  print(card_border_bottom())
183
183
 
184
184
 
@@ -186,13 +186,18 @@ def print_step_2_profile(detected_stack=None):
186
186
  """Print the security profile & coverage card (in-process stack alignment)."""
187
187
  print(card_border_top("Step 2/3 ─── Security Profile & Coverage"))
188
188
  print(card_line(""))
189
- print(card_line(f"{BOLD}Rule Families:{RESET}"))
190
- print(card_line(f" {YELLOW}TG-SEC{RESET} Secrets & Credentials {YELLOW}TG-DB{RESET} Database Safety"))
191
- print(card_line(f" {YELLOW}TG-INPUT{RESET} Input Validation {YELLOW}TG-AUTH{RESET} Authentication"))
192
- print(card_line(f" {YELLOW}TG-CLIENT{RESET} Client Bundle Leaks {YELLOW}TG-DIFF{RESET} Diff Inspection"))
193
- print(card_line(f" {YELLOW}TG-AGENT{RESET} AI Agent Security {YELLOW}TG-EDGE{RESET} Serverless"))
194
- print(card_line(f" {YELLOW}TG-SUPPLY{RESET} Supply Chain & CI/CD {YELLOW}TG-SSRF{RESET} Outbound Net"))
195
- print(card_line(f" {YELLOW}TG-BIZ{RESET} Business Logic"))
189
+ print(card_line(f"{BOLD}Rule Families (88 Rules Across 22 Families):{RESET}"))
190
+ print(card_line(f" {YELLOW}TG-SEC{RESET} Secrets & Tokens {YELLOW}TG-AUTH{RESET} Authentication"))
191
+ print(card_line(f" {YELLOW}TG-DB{RESET} Database Isolation {YELLOW}TG-INPUT{RESET} Input Sanitization"))
192
+ print(card_line(f" {YELLOW}TG-RATE{RESET} Rate Limiting {YELLOW}TG-AGENT{RESET} AI Prompt Injection"))
193
+ print(card_line(f" {YELLOW}TG-SSRF{RESET} Server-Side Request {YELLOW}TG-WEBHOOK{RESET} Webhook Signature"))
194
+ print(card_line(f" {YELLOW}TG-WS{RESET} WebSocket Safety {YELLOW}TG-CSRF{RESET} Cross-Site Request"))
195
+ print(card_line(f" {YELLOW}TG-GQL{RESET} GraphQL Introspection {YELLOW}TG-SUPPLY{RESET} Supply Chain Health"))
196
+ print(card_line(f" {YELLOW}TG-BIZ{RESET} Business Logic Limits {YELLOW}TG-CACHE{RESET} Cache Poisoning"))
197
+ print(card_line(f" {YELLOW}TG-CLIENT{RESET} Client Bundle Secrets {YELLOW}TG-PLATFORM{RESET}Platform Hardening"))
198
+ print(card_line(f" {YELLOW}TG-DIFF{RESET} Polyglot Bypass Guard {YELLOW}TG-EDGE{RESET} Edge & Serverless"))
199
+ print(card_line(f" {YELLOW}TG-CONT{RESET} Container Hardening {YELLOW}TG-GIT{RESET} Git Secret Mining"))
200
+ print(card_line(f" {YELLOW}TG-REDOS{RESET} ReDoS Complexity Guard {YELLOW}TG-RAG{RESET} RAG & Vector Scoping"))
196
201
  print(card_line(""))
197
202
  print(card_line(f"{BOLD}Supported Stacks:{RESET}"))
198
203
  print(card_line(f" {GREEN}Python{RESET} Django · FastAPI · Flask · DRF · SQLAlchemy"))
@@ -227,7 +232,7 @@ def print_success_card():
227
232
  print(card_line("", border="║", border_color=GREEN))
228
233
  print(card_line(f"{BOLD}Next Steps:{RESET}", border="║", border_color=GREEN))
229
234
  print(card_line("", border="║", border_color=GREEN))
230
- print(card_line(f" {CYAN}1.{RESET} In AI Chat {WHITE}/torusguard-audit{RESET} or {WHITE}/torusguard{RESET}", border="║", border_color=GREEN))
235
+ print(card_line(f" {CYAN}1.{RESET} In AI Chat {WHITE}/torusguard audit{RESET} or {WHITE}/torusguard status{RESET}", border="║", border_color=GREEN))
231
236
  print(card_line(f" {CYAN}2.{RESET} In Terminal {WHITE}npx torusguard status{RESET}", border="║", border_color=GREEN))
232
237
  print(card_line(f" {CYAN}3.{RESET} In CI/CD {WHITE}npx torusguard audit{RESET}", border="║", border_color=GREEN))
233
238
  print(card_line("", border="║", border_color=GREEN))
@@ -238,16 +243,21 @@ def print_success_card():
238
243
 
239
244
 
240
245
  def print_already_initialized(target_root, cfg):
241
- """Print the already-initialized status card."""
246
+ """Print the already-initialized status card with dynamic width alignment."""
242
247
  print()
243
248
  top = f" {CYAN}╭{'─' * 71}╮{RESET}"
244
249
  bottom = f" {CYAN}╰{'─' * 71}╯{RESET}"
245
- title_line = card_line(f"{BOLD}{WHITE}🛡️ TORUSGUARD WORKSPACE{RESET}{' ' * 28}{GREEN}[Active]{RESET}")
250
+ title_text = f"{BOLD}{WHITE}🛡️ TORUSGUARD WORKSPACE{RESET}"
251
+ status_text = f"{GREEN}[Active]{RESET}"
252
+ title_vis = get_visual_width("🛡️ TORUSGUARD WORKSPACE")
253
+ status_vis = get_visual_width("[Active]")
254
+ pad_count = max(1, 67 - title_vis - status_vis)
255
+ title_line = card_line(f"{title_text}{' ' * pad_count}{status_text}")
246
256
  print(f"{top}\n{title_line}\n{bottom}")
247
257
  print(f"""
248
258
  {BOLD}▸ Project Root:{RESET} {GREEN}{target_root}{RESET}
249
259
  {BOLD}▸ Workspace:{RESET} {GREEN}.torusguard/{RESET} {DIM}(Already Initialized){RESET}
250
- {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '2.1.1')}{RESET}
260
+ {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '2.1.3')}{RESET}
251
261
  {BOLD}▸ Severity Floor:{RESET} {YELLOW}{cfg.get('severity_threshold', 'medium')}{RESET}
252
262
 
253
263
  {DIM}To refresh templates or re-scaffold, run:{RESET}
@@ -454,53 +464,10 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
454
464
  3. Follow the phase execution steps defined in the workflow.
455
465
  """
456
466
 
457
- # Ensure .agents/workflows, .agents/skills, .agent/workflows, and .agent/skills are created
458
- dest_workflow_dirs = []
459
-
460
- # 1. Antigravity / Gemini (.agents/)
461
- agents_wf = target_root / ".agents" / "workflows"
462
- agents_wf.mkdir(parents=True, exist_ok=True)
463
- (agents_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
464
- dest_workflow_dirs.append(agents_wf)
465
- registered_ides.append("Antigravity / Gemini .agents/workflows/torusguard.md")
466
-
467
- # 2. Tribunal Agent Kit (.agent/)
468
- agent_wf = target_root / ".agent" / "workflows"
469
- agent_wf.mkdir(parents=True, exist_ok=True)
470
- (agent_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
471
- dest_workflow_dirs.append(agent_wf)
472
- registered_ides.append("Tribunal Agent Kit .agent/workflows/torusguard.md")
473
-
474
- # Unpack Skills into .agents/skills and .agent/skills for full IDE resolution
475
- src_skills = torusguard_target / "skills"
476
- if src_skills.is_dir():
477
- for dest_base in [target_root / ".agents" / "skills", target_root / ".agent" / "skills"]:
478
- dest_base.mkdir(parents=True, exist_ok=True)
479
- for skill_dir in src_skills.iterdir():
480
- if skill_dir.is_dir():
481
- target_skill_dir = dest_base / skill_dir.name
482
- if not target_skill_dir.exists():
483
- try:
484
- shutil.copytree(skill_dir, target_skill_dir)
485
- except Exception:
486
- pass
487
-
488
- # When full_commands is requested (e.g. via NPM package npx torusguard init),
489
- # unlock and register all individual slash commands
490
- if full_commands:
491
- src_wf = torusguard_target / "workflows"
492
- if src_wf.is_dir():
493
- count = 0
494
- for wf_file in src_wf.glob("*.md"):
495
- if wf_file.name == "torusguard.md":
496
- continue
497
- cmd_filename = f"torusguard-{wf_file.name}"
498
- for d in dest_workflow_dirs:
499
- shutil.copy2(wf_file, d / cmd_filename)
500
- count += 1
501
- registered_ides.append(f"{count} Slash Commands /torusguard-audit, -harden, -apply, ...")
502
-
503
- # Claude Code (.claude/commands)
467
+ # Core workspace governance is self-contained in .torusguard/
468
+ registered_ides.append("Workspace Core .torusguard/ (Workflows & Skills)")
469
+
470
+ # Claude Code (.claude/commands) - only if .claude exists
504
471
  claude_dir = target_root / ".claude"
505
472
  if claude_dir.exists():
506
473
  claude_commands = claude_dir / "commands"
@@ -508,7 +475,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
508
475
  (claude_commands / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
509
476
  registered_ides.append("Claude Code .claude/commands/torusguard.md")
510
477
 
511
- # Cursor (.cursor/rules)
478
+ # Cursor (.cursor/rules) - only if .cursor exists
512
479
  cursor_dir = target_root / ".cursor"
513
480
  if cursor_dir.exists():
514
481
  cursor_rules = cursor_dir / "rules"
@@ -9,7 +9,7 @@
9
9
  "agents/validator.md": "79fc4431de5c5507f8730aee6c5c3e61fd238cbf8cf8c7c6aac462eee9761ed6",
10
10
  "config/scope.json": "b198a86186b4c6d5e1af516bf4e3a6afa8878e622ca1d57a5bf72d294f8c6f25",
11
11
  "config/slash-commands.json": "305c1dc5b556e8d64ad9dd585dafac1a9955cf1bd5321429955b19b7a62736b6",
12
- "config/torusguard.json": "55dbde335997421a01c97709fd1672ad70fa921bfe8346dd57552b799db2419e",
12
+ "config/torusguard.json": "e8e41f3be04a06deb32ce5faaa93ddd608abfb2694b30325cac5085f3bfec9d8",
13
13
  "core/__init__.py": "2120562452ae03c84468d67246dc93376f7ebcde8e4ca767c6253bc92c35dbbf",
14
14
  "core/agent_roles.py": "d7189dbf1d3ae4e330eb316bed5d399a18992295addf466f4c6552bc14ae6a34",
15
15
  "core/ast_walker.py": "309564d168e6eb9e3e93aceb29a95a61872b35a4da7235ee49e79e9d3a5e7cc6",
@@ -215,11 +215,11 @@
215
215
  "scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
216
216
  "scripts/sarif_exporter.py": "86700765212adb3ab590ca72614bf3ad4ce7ce60e3193f7f3bd1a04d34d10f6e",
217
217
  "scripts/stack_detect.py": "c05a1ade4c8692025476bf7ea080a8f07c92e5d8e9a04f94c1654386352ffbdc",
218
- "scripts/status_runner.py": "4c358c91950c7874bcc6a5f23f2d3fda62b0752efcf6c6b658adf02ed77c7752",
219
- "scripts/stride_generator.py": "4660713fa65e24119b88b6a050fb41f625d99bad030f1db40d198950d8c55ba8",
220
- "scripts/term_ui.py": "ca69398f85c86fe89526d6334b3ee866c890273997351113c3cc1765b7bd20c3",
218
+ "scripts/status_runner.py": "a7421e25e2e34c1b83960ad117f5ea23d6f08b8af8b664be3fe03f70a3962db3",
219
+ "scripts/stride_generator.py": "6db98e8d9272c3c69f7c9be71cc4d9db6fe48553a3d7850ca62399ce4471ece8",
220
+ "scripts/term_ui.py": "a23435c703c4e8b68c5b80a539d59de2eda1cb01b0d9c47909ba72efde3be29b",
221
221
  "skills/torusguard/SKILL.md": "15c69cb10eca1a10344b494888dce57e2baf227c3282bd54424a36ce35fb2460",
222
- "skills/torusguard/bootstrap.py": "b75ad49e9dade87980cde3269ee1f5c3438f944a34a545c44f839d4496086b63",
222
+ "skills/torusguard/bootstrap.py": "178145eb36d15974ec9833d5c434dd31bba955d40a04cc9c12aed04058d1936a",
223
223
  "skills/torusguard/references/auth-and-sessions.md": "c3e4b9600cb53fc28c993922dc880accbec5783ac90d5ee98d63b52762d19525",
224
224
  "skills/torusguard/references/business-logic-and-abuse.md": "58e87df2864d468af70c1ff39f5d540c687fa846b671457f85046ab2065fe99c",
225
225
  "skills/torusguard/references/cache-and-sensitive-responses.md": "81b4a7a08e11dafa4ec58d868c4a35f1f891d0dcdcfbcefaef81e1b9ba94f5a1",
@@ -262,9 +262,9 @@
262
262
  "skills/torusguard-recheck/SKILL.md": "a5c4539ec6d091179c8ba53792fba46f26795976f392d2305e357f25a2966c55",
263
263
  "skills/torusguard-redos/SKILL.md": "b09b39bd98589613b2107c177e247f6224fb54ab2f028b4339ae01aac9d28c67",
264
264
  "skills/torusguard-report/SKILL.md": "509185ea6730601cf9a44e136219cace61cd0523f8e112de03e4ef1c35e60585",
265
- "skills/torusguard-review/SKILL.md": "6d9ec907821ddf62bbbeaed8751d1532e72ba42702ea3afdaadaf720f66c35e3",
265
+ "skills/torusguard-review/SKILL.md": "0c540a587befee455f027d752e261ed5885ec21def2c52471bd29bec69178307",
266
266
  "skills/torusguard-status/SKILL.md": "e9741a20313a8304bc7565b194949a59ec7cfd4945b197517680164b3197efc0",
267
- "skills/torusguard-threatmodel/SKILL.md": "549903f39a030a75d88c184b7373d86bca921d8f802732c3674bfe9537b14537",
267
+ "skills/torusguard-threatmodel/SKILL.md": "3f589ea931998475536e25c77f85ddc17447012f860b4cee8d75e7b0f219ce82",
268
268
  "skills/torusguard-verify/SKILL.md": "aeb4d3c7924253607d130e48491d83bf7b7a21707cd1dac2ba97d64f5e259fd6",
269
269
  "skills/torusguard-web-validate/SKILL.md": "f1df00e10abd823d9a8c4daa1a3af7f26c5263c6c8e58e05b61b647d01a25489",
270
270
  "templates/audit-report.template.md": "71149dd05b01a74287a47781fdc71fd2d1b4b70337da303bf78767d0410a6c90",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "../schemas/torusguard-config.schema.json",
3
- "version": "1.0.0",
3
+ "version": "2.1.3",
4
4
  "product": "TorusGuard Security Skill Kit",
5
5
  "severity_threshold": "medium",
6
6
  "auto_detect_stack": true,
@@ -58,7 +58,7 @@ def collect_status(target_dir: Path) -> WorkspaceStatus:
58
58
  is_init = tg_dir.is_dir()
59
59
 
60
60
  # 1. Read config
61
- version = "1.4.0"
61
+ version = "2.1.3"
62
62
  stack_name = "Undetected"
63
63
  cfg_file = tg_dir / "config" / "torusguard.json"
64
64
  if cfg_file.is_file():
@@ -94,7 +94,7 @@ def collect_status(target_dir: Path) -> WorkspaceStatus:
94
94
  if rules_root.is_dir():
95
95
  active_rules_count = sum(1 for f in rules_root.rglob("TG-*.md"))
96
96
  if active_rules_count == 0:
97
- active_rules_count = 74 # Canonical rule catalog default
97
+ active_rules_count = 88 # Canonical rule catalog default
98
98
 
99
99
  # 3. Read run history
100
100
  total_runs = 0
@@ -210,7 +210,7 @@ def print_status_card(status: WorkspaceStatus) -> None:
210
210
  print(format_box_line(f"Workspace: {WHITE}{status.target_path}{RESET}", 67))
211
211
  print(format_box_line(f"Status: {init_str}", 67))
212
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))
213
+ print(format_box_line(f"Active Rules: {GREEN}{status.active_rules_count}{RESET} canonical rules enabled across 22 families", 67))
214
214
  print(card_border_bottom(CYAN))
215
215
  print()
216
216
 
@@ -142,7 +142,7 @@ def generate_stride_report(root_dir: Path) -> str:
142
142
 
143
143
  report = f"""# TorusGuard Architectural Threat Model & STRIDE Register
144
144
 
145
- **Generated by:** TorusGuard Threat Modeling Engine (v2.1.2)
145
+ **Generated by:** TorusGuard Threat Modeling Engine (v2.1.3)
146
146
  **Workspace:** `{root_dir.resolve().as_posix()}`
147
147
  **Analyzed Routes:** {comp['total_routes_detected']}
148
148
  **Identified Data Stores:** {', '.join(comp['datastores'])}
@@ -143,7 +143,7 @@ def card_divider(title: str = "", border_color: str = CYAN, double: bool = False
143
143
  return f" {border_color}{left}{h} {BOLD}{WHITE}{title}{RESET}{border_color} {h * rem}{right}{RESET}"
144
144
  return f" {border_color}{left}{h * 71}{right}{RESET}"
145
145
 
146
- def card_header(title: str, subtitle: str = "", version: str = "v1.3.4", border_color: str = CYAN) -> str:
146
+ def card_header(title: str, subtitle: str = "", version: str = "v2.1.3", border_color: str = CYAN) -> str:
147
147
  """Generate standardized 75-column curved header box."""
148
148
  top = f" {border_color}╭{'─' * 71}╮{RESET}"
149
149
  bottom = f" {border_color}╰{'─' * 71}╯{RESET}"
@@ -144,7 +144,7 @@ def card_divider(title: str = "", border_color: str = CYAN, double: bool = False
144
144
  return f" {border_color}{left}{h} {BOLD}{WHITE}{title}{RESET}{border_color} {h * rem}{right}{RESET}"
145
145
  return f" {border_color}{left}{h * 71}{right}{RESET}"
146
146
 
147
- def card_header(title: str, subtitle: str = "", version: str = "v2.1.2", border_color: str = CYAN) -> str:
147
+ def card_header(title: str, subtitle: str = "", version: str = "v2.1.3", border_color: str = CYAN) -> str:
148
148
  """Generate standardized 75-column curved header box."""
149
149
  top = f" {border_color}╭{'─' * 71}╮{RESET}"
150
150
  bottom = f" {border_color}╰{'─' * 71}╯{RESET}"
@@ -164,7 +164,7 @@ def card_header(title: str, subtitle: str = "", version: str = "v2.1.2", border_
164
164
  def print_header():
165
165
  """Print the branded TorusGuard header card."""
166
166
  print()
167
- print(card_header("🛡️ T O R U S G U A R D", "Autonomous Security Engine for AI-Built Applications", version="v2.1.2"))
167
+ print(card_header("🛡️ T O R U S G U A R D", "Autonomous Security Engine for AI-Built Applications", version="v2.1.3"))
168
168
  print()
169
169
 
170
170
 
@@ -172,13 +172,13 @@ def print_step_1_assets(file_count):
172
172
  """Print the enhanced Step 1 asset unpacking card."""
173
173
  print(card_border_top("Step 1/3 ─── Unpacking Governance Assets"))
174
174
  print(card_line(""))
175
- print(card_line(f"{GREEN}✔{RESET} Canonical security rules {DIM}71 rules across 11 families{RESET}"))
175
+ print(card_line(f"{GREEN}✔{RESET} Canonical security rules {DIM}88 rules across 22 families{RESET}"))
176
176
  print(card_line(f"{GREEN}✔{RESET} JSON validation schemas {DIM}8 formal schemas{RESET}"))
177
177
  print(card_line(f"{GREEN}✔{RESET} Specialist agent specifications {DIM}5 isolated agents{RESET}"))
178
- print(card_line(f"{GREEN}✔{RESET} Workflow templates {DIM}11 slash commands{RESET}"))
179
- print(card_line(f"{GREEN}✔{RESET} Framework reference guides {DIM}10 security guides{RESET}"))
178
+ print(card_line(f"{GREEN}✔{RESET} Governed workflow templates {DIM}25 commands & 13 MCP tools{RESET}"))
179
+ print(card_line(f"{GREEN}✔{RESET} Framework reference guides {DIM}22 architectural guides{RESET}"))
180
180
  print(card_line(""))
181
- print(card_line(f"{BOLD}{WHITE}{file_count} files unpacked{RESET}"))
181
+ print(card_line(f"{BOLD}{WHITE}{file_count} files unpacked into .torusguard/{RESET}"))
182
182
  print(card_border_bottom())
183
183
 
184
184
 
@@ -186,13 +186,18 @@ def print_step_2_profile(detected_stack=None):
186
186
  """Print the security profile & coverage card (in-process stack alignment)."""
187
187
  print(card_border_top("Step 2/3 ─── Security Profile & Coverage"))
188
188
  print(card_line(""))
189
- print(card_line(f"{BOLD}Rule Families:{RESET}"))
190
- print(card_line(f" {YELLOW}TG-SEC{RESET} Secrets & Credentials {YELLOW}TG-DB{RESET} Database Safety"))
191
- print(card_line(f" {YELLOW}TG-INPUT{RESET} Input Validation {YELLOW}TG-AUTH{RESET} Authentication"))
192
- print(card_line(f" {YELLOW}TG-CLIENT{RESET} Client Bundle Leaks {YELLOW}TG-DIFF{RESET} Diff Inspection"))
193
- print(card_line(f" {YELLOW}TG-AGENT{RESET} AI Agent Security {YELLOW}TG-EDGE{RESET} Serverless"))
194
- print(card_line(f" {YELLOW}TG-SUPPLY{RESET} Supply Chain & CI/CD {YELLOW}TG-SSRF{RESET} Outbound Net"))
195
- print(card_line(f" {YELLOW}TG-BIZ{RESET} Business Logic"))
189
+ print(card_line(f"{BOLD}Rule Families (88 Rules Across 22 Families):{RESET}"))
190
+ print(card_line(f" {YELLOW}TG-SEC{RESET} Secrets & Tokens {YELLOW}TG-AUTH{RESET} Authentication"))
191
+ print(card_line(f" {YELLOW}TG-DB{RESET} Database Isolation {YELLOW}TG-INPUT{RESET} Input Sanitization"))
192
+ print(card_line(f" {YELLOW}TG-RATE{RESET} Rate Limiting {YELLOW}TG-AGENT{RESET} AI Prompt Injection"))
193
+ print(card_line(f" {YELLOW}TG-SSRF{RESET} Server-Side Request {YELLOW}TG-WEBHOOK{RESET} Webhook Signature"))
194
+ print(card_line(f" {YELLOW}TG-WS{RESET} WebSocket Safety {YELLOW}TG-CSRF{RESET} Cross-Site Request"))
195
+ print(card_line(f" {YELLOW}TG-GQL{RESET} GraphQL Introspection {YELLOW}TG-SUPPLY{RESET} Supply Chain Health"))
196
+ print(card_line(f" {YELLOW}TG-BIZ{RESET} Business Logic Limits {YELLOW}TG-CACHE{RESET} Cache Poisoning"))
197
+ print(card_line(f" {YELLOW}TG-CLIENT{RESET} Client Bundle Secrets {YELLOW}TG-PLATFORM{RESET}Platform Hardening"))
198
+ print(card_line(f" {YELLOW}TG-DIFF{RESET} Polyglot Bypass Guard {YELLOW}TG-EDGE{RESET} Edge & Serverless"))
199
+ print(card_line(f" {YELLOW}TG-CONT{RESET} Container Hardening {YELLOW}TG-GIT{RESET} Git Secret Mining"))
200
+ print(card_line(f" {YELLOW}TG-REDOS{RESET} ReDoS Complexity Guard {YELLOW}TG-RAG{RESET} RAG & Vector Scoping"))
196
201
  print(card_line(""))
197
202
  print(card_line(f"{BOLD}Supported Stacks:{RESET}"))
198
203
  print(card_line(f" {GREEN}Python{RESET} Django · FastAPI · Flask · DRF · SQLAlchemy"))
@@ -227,7 +232,7 @@ def print_success_card():
227
232
  print(card_line("", border="║", border_color=GREEN))
228
233
  print(card_line(f"{BOLD}Next Steps:{RESET}", border="║", border_color=GREEN))
229
234
  print(card_line("", border="║", border_color=GREEN))
230
- print(card_line(f" {CYAN}1.{RESET} In AI Chat {WHITE}/torusguard-audit{RESET} or {WHITE}/torusguard{RESET}", border="║", border_color=GREEN))
235
+ print(card_line(f" {CYAN}1.{RESET} In AI Chat {WHITE}/torusguard audit{RESET} or {WHITE}/torusguard status{RESET}", border="║", border_color=GREEN))
231
236
  print(card_line(f" {CYAN}2.{RESET} In Terminal {WHITE}npx torusguard status{RESET}", border="║", border_color=GREEN))
232
237
  print(card_line(f" {CYAN}3.{RESET} In CI/CD {WHITE}npx torusguard audit{RESET}", border="║", border_color=GREEN))
233
238
  print(card_line("", border="║", border_color=GREEN))
@@ -238,16 +243,21 @@ def print_success_card():
238
243
 
239
244
 
240
245
  def print_already_initialized(target_root, cfg):
241
- """Print the already-initialized status card."""
246
+ """Print the already-initialized status card with dynamic width alignment."""
242
247
  print()
243
248
  top = f" {CYAN}╭{'─' * 71}╮{RESET}"
244
249
  bottom = f" {CYAN}╰{'─' * 71}╯{RESET}"
245
- title_line = card_line(f"{BOLD}{WHITE}🛡️ TORUSGUARD WORKSPACE{RESET}{' ' * 28}{GREEN}[Active]{RESET}")
250
+ title_text = f"{BOLD}{WHITE}🛡️ TORUSGUARD WORKSPACE{RESET}"
251
+ status_text = f"{GREEN}[Active]{RESET}"
252
+ title_vis = get_visual_width("🛡️ TORUSGUARD WORKSPACE")
253
+ status_vis = get_visual_width("[Active]")
254
+ pad_count = max(1, 67 - title_vis - status_vis)
255
+ title_line = card_line(f"{title_text}{' ' * pad_count}{status_text}")
246
256
  print(f"{top}\n{title_line}\n{bottom}")
247
257
  print(f"""
248
258
  {BOLD}▸ Project Root:{RESET} {GREEN}{target_root}{RESET}
249
259
  {BOLD}▸ Workspace:{RESET} {GREEN}.torusguard/{RESET} {DIM}(Already Initialized){RESET}
250
- {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '2.1.1')}{RESET}
260
+ {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '2.1.3')}{RESET}
251
261
  {BOLD}▸ Severity Floor:{RESET} {YELLOW}{cfg.get('severity_threshold', 'medium')}{RESET}
252
262
 
253
263
  {DIM}To refresh templates or re-scaffold, run:{RESET}
@@ -454,53 +464,10 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
454
464
  3. Follow the phase execution steps defined in the workflow.
455
465
  """
456
466
 
457
- # Ensure .agents/workflows, .agents/skills, .agent/workflows, and .agent/skills are created
458
- dest_workflow_dirs = []
459
-
460
- # 1. Antigravity / Gemini (.agents/)
461
- agents_wf = target_root / ".agents" / "workflows"
462
- agents_wf.mkdir(parents=True, exist_ok=True)
463
- (agents_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
464
- dest_workflow_dirs.append(agents_wf)
465
- registered_ides.append("Antigravity / Gemini .agents/workflows/torusguard.md")
466
-
467
- # 2. Tribunal Agent Kit (.agent/)
468
- agent_wf = target_root / ".agent" / "workflows"
469
- agent_wf.mkdir(parents=True, exist_ok=True)
470
- (agent_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
471
- dest_workflow_dirs.append(agent_wf)
472
- registered_ides.append("Tribunal Agent Kit .agent/workflows/torusguard.md")
473
-
474
- # Unpack Skills into .agents/skills and .agent/skills for full IDE resolution
475
- src_skills = torusguard_target / "skills"
476
- if src_skills.is_dir():
477
- for dest_base in [target_root / ".agents" / "skills", target_root / ".agent" / "skills"]:
478
- dest_base.mkdir(parents=True, exist_ok=True)
479
- for skill_dir in src_skills.iterdir():
480
- if skill_dir.is_dir():
481
- target_skill_dir = dest_base / skill_dir.name
482
- if not target_skill_dir.exists():
483
- try:
484
- shutil.copytree(skill_dir, target_skill_dir)
485
- except Exception:
486
- pass
487
-
488
- # When full_commands is requested (e.g. via NPM package npx torusguard init),
489
- # unlock and register all individual slash commands
490
- if full_commands:
491
- src_wf = torusguard_target / "workflows"
492
- if src_wf.is_dir():
493
- count = 0
494
- for wf_file in src_wf.glob("*.md"):
495
- if wf_file.name == "torusguard.md":
496
- continue
497
- cmd_filename = f"torusguard-{wf_file.name}"
498
- for d in dest_workflow_dirs:
499
- shutil.copy2(wf_file, d / cmd_filename)
500
- count += 1
501
- registered_ides.append(f"{count} Slash Commands /torusguard-audit, -harden, -apply, ...")
502
-
503
- # Claude Code (.claude/commands)
467
+ # Core workspace governance is self-contained in .torusguard/
468
+ registered_ides.append("Workspace Core .torusguard/ (Workflows & Skills)")
469
+
470
+ # Claude Code (.claude/commands) - only if .claude exists
504
471
  claude_dir = target_root / ".claude"
505
472
  if claude_dir.exists():
506
473
  claude_commands = claude_dir / "commands"
@@ -508,7 +475,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
508
475
  (claude_commands / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
509
476
  registered_ides.append("Claude Code .claude/commands/torusguard.md")
510
477
 
511
- # Cursor (.cursor/rules)
478
+ # Cursor (.cursor/rules) - only if .cursor exists
512
479
  cursor_dir = target_root / ".cursor"
513
480
  if cursor_dir.exists():
514
481
  cursor_rules = cursor_dir / "rules"
@@ -2,8 +2,8 @@
2
2
  name: torusguard-review
3
3
  description: Differential PR and Git diff incremental security review — detects newly introduced vulnerabilities between Git branches or commits with net security score deltas.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
- version: 2.1.2
6
- last-updated: 2026-09-30
5
+ version: 2.1.3
6
+ last-updated: 2026-10-01
7
7
  skills:
8
8
  - torusguard
9
9
  - torusguard-audit
@@ -2,8 +2,8 @@
2
2
  name: torusguard-threatmodel
3
3
  description: Synthesizes an architectural STRIDE threat model, interactive Mermaid Data Flow Diagram (DFD), and trust boundary register into SECURITY_THREAT_MODEL.md.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
- version: 2.1.2
6
- last-updated: 2026-09-30
5
+ version: 2.1.3
6
+ last-updated: 2026-10-01
7
7
  skills:
8
8
  - torusguard
9
9
  - torusguard-audit
@@ -2,8 +2,8 @@
2
2
  name: torusguard-review
3
3
  description: Differential PR and Git diff incremental security review — detects newly introduced vulnerabilities between Git branches or commits with net security score deltas.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
- version: 2.1.2
6
- last-updated: 2026-09-30
5
+ version: 2.1.3
6
+ last-updated: 2026-10-01
7
7
  skills:
8
8
  - torusguard
9
9
  - torusguard-audit
@@ -2,8 +2,8 @@
2
2
  name: torusguard-threatmodel
3
3
  description: Synthesizes an architectural STRIDE threat model, interactive Mermaid Data Flow Diagram (DFD), and trust boundary register into SECURITY_THREAT_MODEL.md.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
- version: 2.1.2
6
- last-updated: 2026-09-30
5
+ version: 2.1.3
6
+ last-updated: 2026-10-01
7
7
  skills:
8
8
  - torusguard
9
9
  - torusguard-audit