pkg-scaffold 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ # ============================================================================
2
+ # ⚙️ pkg-scaffold Rule Suppression & Intent Profiles
3
+ # ============================================================================
4
+ # Define exact symbols, file patterns, or dependency keys that must remain
5
+ # preserved during dead-code scanning and transactional refactoring pruning.
6
+
7
+ # Framework & Meta Entrypoints (Implicitly Alive)
8
+ pages/api/*
9
+ app/routes/*
10
+ src/entry-point.js
11
+
12
+ # Intent Suppression: Library Code / Consumer Consumption Contracts
13
+ export:publicApiMethod
14
+ export:initializePlugin
15
+ export:onConfigLoaded
16
+
17
+ # Globally Ignored Module Specifiers
18
+ @types/node
19
+ tslib
20
+
21
+ # Secret Heuristic Exemptions (Explicit False Positive Control)
22
+ exempt_token_pattern
package/README.md CHANGED
@@ -1,107 +1,94 @@
1
- # 🚀 pkg-scaffold
2
-
3
- **Advanced Dependency Intelligence & Zero-Config Workspace Initializer**
4
-
5
- `pkg-scaffold` is a high-performance CLI tool designed to audit, clean, and initialize your JavaScript/TypeScript workspaces. It goes far beyond simple scaffolding by analyzing your source code's Abstract Syntax Tree (AST) to find critical issues like undeclared dependencies, orphaned packages, and security leaks.
6
-
7
-
8
- [![npm version](https://img.shields.io/npm/v/pkg-scaffold.svg?style=flat&color=CB3837)](https://www.npmjs.com/package/pkg-scaffold)
9
- [![npm downloads](https://img.shields.io/npm/dm/pkg-scaffold.svg?style=flat&color=34ADFF)](https://www.npmjs.com/package/pkg-scaffold)
10
- [![License](https://img.shields.io/badge/license-MIT-orange.svg?style=flat)](LICENSE)
11
- [![GitHub stars](https://img.shields.io/github/stars/DreamLongYT/pkg-scaffold.svg?style=flat&color=gold)](https://github.com/DreamLongYT/pkg-scaffold/stargazers)
12
-
13
- ---
14
-
15
- ## ✨ Why pkg-scaffold?
16
-
17
- Most tools just create a `package.json`. `pkg-scaffold` **understands** your code. It bridges the gap between your source files and your configuration.
18
-
19
- ### 🔍 Deep Intelligence Features
20
-
21
- * **🚨 Ghost Dependency Detection**: Finds packages you `import` in your code but forgot to add to `package.json`. These are critical errors that will break your CI/CD or production builds.
22
- * **🗑️ Orphaned Package Identification**: Finds packages listed in your `package.json` that are never actually used in your code. Perfect for reducing bundle size and "dependency bloat".
23
- * **⚡ Unused Import Auditor**: Pinpoints specific files and line numbers where a package is imported but its identifier is never referenced.
24
- * **🔐 Security Compliance**: Automatically scans for hardcoded secrets (API keys, tokens, passwords) and offers to move them safely into `.env` files.
25
- * **📛 Deprecation Guard**: Live-checks your dependencies against the npm registry to warn you about deprecated or non-existent packages.
26
- * **🏗️ Intelligent Scaffolding**: Detects your framework (React, Vue, Svelte, Next.js, etc.) and automatically generates optimized `tsconfig.json`, `eslint.config.js`, `.prettierrc`, and `.gitignore`.
27
- * **📦 Monorepo Ready**: Automatically detects sub-workspaces and offers to set up `pnpm-workspace.yaml` or npm/yarn workspaces.
28
-
29
- ---
30
-
31
- ## 🚀 Quick Start
32
-
33
- You don't even need to install it to try it out:
34
-
35
- ```bash
36
- npx pkg-scaffold
37
- ```
38
-
39
- Or install it globally:
40
-
41
- ```bash
42
- npm install -g pkg-scaffold
43
- # then run
44
- pkg-scaffold
45
- ```
46
-
47
- ---
48
-
49
- ## 🛠️ How it works
50
-
51
- ### 1. The Scan
52
- `pkg-scaffold` crawls your workspace, ignoring `node_modules` and build artifacts. It parses every `.js`, `.ts`, `.jsx`, and `.tsx` file using a high-performance AST engine.
53
-
54
- ### 2. The Analysis
55
- It maps your imports against your `package.json`. It knows about:
56
- * **Aliases**: Understands that `lodash` is often imported as `_`.
57
- * **Binaries**: Knows that `tsc` comes from `typescript` and `vite` from `vite`.
58
- * **Type-only imports**: Correctly handles TypeScript `import type` without flagging them as unused.
59
- * **Side-effects**: Detects `import 'css-file'` or polyfills correctly.
60
-
61
- ### 3. The Fix
62
- The tool is interactive. It will ask you before:
63
- * Adding missing (ghost) dependencies.
64
- * Pruning unused (orphaned) packages.
65
- * Injecting `dotenv` initialization.
66
- * Moving secrets to `.env`.
67
-
68
- ---
69
-
70
- ## 📊 Summary Report
71
- At the end of every run, you get a clear intelligence summary:
72
-
73
- ```text
74
- ═══════════════════════════════════════════════════════════════════
75
- 📊 DEPENDENCY INTELLIGENCE SUMMARY
76
- ═══════════════════════════════════════════════════════════════════
77
- 📁 Files scanned: 42
78
- 📦 Packages imported: 18
79
- 🚨 Ghost deps (missing): 2 — CRITICAL
80
- 🗑️ Orphaned deps (unused): 3
81
- Unused imports: 5
82
- 📛 Deprecated packages: 1
83
- 🔐 Hardcoded secrets: 1 — SECURITY RISK
84
- ═══════════════════════════════════════════════════════════════════
85
- ```
86
-
87
- ---
88
-
89
- ## 🤝 Contributing
90
-
91
- Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
92
-
93
- 1. Fork the Project
94
- 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
95
- 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
96
- 4. Push to the Branch (`git push origin feature/AmazingFeature`)
97
- 5. Open a Pull Request
98
-
99
- ---
100
-
101
- ## 📄 License
102
-
103
- Distributed under the MIT License. See `LICENSE` for more information.
104
-
105
- ---
106
-
107
- **Built with ❤️ by [DreamLongYT](https://github.com/DreamLongYT)**
1
+ # 📦 pkg-scaffold v3.0.0
2
+
3
+ **Enterprise-Grade AST Syntax Refactoring & Self-Healing Engine**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/pkg-scaffold.svg?style=flat&color=CB3837)](https://www.npmjs.com/package/pkg-scaffold)
6
+ [![npm downloads](https://img.shields.io/npm/dm/pkg-scaffold.svg?style=flat&color=34ADFF)](https://www.npmjs.com/package/pkg-scaffold)
7
+ [![License](https://img.shields.io/badge/license-MIT-orange.svg?style=flat)](LICENSE)
8
+ [![GitHub stars](https://img.shields.io/github/stars/DreamLongYT/pkg-scaffold.svg?style=flat&color=gold)](https://github.com/DreamLongYT/pkg-scaffold)
9
+
10
+ `pkg-scaffold` is an advanced, AST-driven tool designed to prune dead code, orphaned files, and unused exports from your JavaScript and TypeScript codebases with unprecedented safety. Unlike traditional linters, `pkg-scaffold` doesn't just report issues—it fixes them within a secure, transactional sandbox.
11
+
12
+ ---
13
+
14
+ ## 🚀 Key Features
15
+
16
+ - **AST-Based Deep Tracing**: Leverages the official TypeScript compiler to trace dependencies through complex barrel files, re-exports, and default export chains.
17
+ - **Automated Self-Healing**: Automatically runs your project's test suite after refactoring. If a regression is detected (non-zero exit code), it triggers an immediate rollback.
18
+ - **Transactional Safety**: All modifications occur in a Git-isolated sandbox with a backup journaling system. Your original state is always recoverable.
19
+ - **Interactive Optimization Plan**: Generates a detailed "dry-run" plan for user confirmation before any file is touched.
20
+ - **Suppression Engine**: Fine-grained control using `@scaffold-suppress` directives to protect specific files or exports from being pruned.
21
+
22
+ ---
23
+
24
+ ## ⚔️ Competitive Analysis: Why pkg-scaffold?
25
+
26
+ While tools like [Knip](https://knip.dev/) or [Depcheck](https://github.com/depcheck/depcheck) are excellent for reporting, `pkg-scaffold` is built for **automated architectural cleanup**.
27
+
28
+ | Feature | **pkg-scaffold** | Knip.dev | Depcheck | ts-prune |
29
+ | :--- | :---: | :---: | :---: | :---: |
30
+ | **Dead Code Detection** | ✅ AST-Deep | ✅ Comprehensive | ⚠️ Regex/Loose | ✅ Basic |
31
+ | **Automated Pruning** | ✅ Native | ⚠️ Experimental | ❌ No | ❌ No |
32
+ | **Self-Healing (Auto-Rollback)** | ✅ **Yes** | ❌ No | ❌ No | ❌ No |
33
+ | **Transaction Sandbox** | **Git + Journal** | No | ❌ No | ❌ No |
34
+ | **Interactive Approval** | ✅ **Yes** | ❌ No | ❌ No | ❌ No |
35
+ | **Barrel File Tracing** | ✅ High-Fidelity | ✅ Good | ❌ No | ⚠️ Limited |
36
+ | **Status** | 🚀 Active | 🚀 Active | 🛠️ Maintenance | 🛠️ Maintenance |
37
+
38
+ > **The Verdict:** `pkg-scaffold` wins when you need a **safe, automated workflow** that guarantees your project stays functional after cleaning up technical debt.
39
+
40
+ ---
41
+
42
+ ## 🛠️ Installation & Usage
43
+
44
+ ### Installation
45
+ ```bash
46
+ npm install -g pkg-scaffold
47
+ ```
48
+
49
+ ### Basic Usage (Dry-Run)
50
+ Analyze your project without making any changes:
51
+ ```bash
52
+ pkg-scaffold --cwd ./my-project --no-fix
53
+ ```
54
+
55
+ ### Active Refactoring (Self-Healing)
56
+ Analyze, prune, and validate with automatic rollback on test failure:
57
+ ```bash
58
+ pkg-scaffold --cwd ./my-project --fix --test-command "npm test"
59
+ ```
60
+
61
+ ### Options
62
+ | Flag | Description | Default |
63
+ | :--- | :--- | :--- |
64
+ | `--cwd <path>` | Execution context root directory | `process.cwd()` |
65
+ | `--fix` | Enable atomic code updates and pruning | `true` |
66
+ | `--test-command` | Script to run for self-healing validation | `npm test` |
67
+ | `--yes` | Skip confirmation prompts | `false` |
68
+ | `--verbose` | Toggle expanded debug telemetry | `false` |
69
+
70
+ ---
71
+
72
+ ## 🛡️ Suppression
73
+
74
+ Protect a file or a specific export from being removed:
75
+
76
+ ```javascript
77
+ /**
78
+ * @scaffold-suppress legacyFunction
79
+ */
80
+ export const legacyFunction = () => {
81
+ // This export is safe even if unused
82
+ };
83
+
84
+ /**
85
+ * @scaffold-suppress
86
+ */
87
+ // This entire file is protected from being flagged as orphaned
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 📜 License
93
+
94
+ MIT © DreamLongYT
package/bin/cli.js ADDED
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ============================================================================
5
+ * 🏁 pkg-scaffold CLI Entry Point
6
+ * ============================================================================
7
+ * Handles option compilation, environment orchestration, option validation,
8
+ * and initiates the primary operational pipeline loop.
9
+ */
10
+
11
+ import { Command } from 'commander';
12
+ import ansis from 'ansis';
13
+ import path from 'path';
14
+ import fs from 'fs/promises';
15
+ import { fileURLToPath } from 'url';
16
+
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = path.dirname(__filename);
19
+
20
+ const program = new Command();
21
+
22
+ async function bootstrap() {
23
+ try {
24
+ const packageJsonPath = path.resolve(__dirname, '../package.json');
25
+ const packageJsonContent = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
26
+
27
+ program
28
+ .name('pkg-scaffold')
29
+ .description(ansis.cyan('Enterprise-Grade AST Syntax Refactoring & Self-Healing Engine'))
30
+ .version(packageJsonContent.version || '3.0.0');
31
+
32
+ program
33
+ .option('-c, --cwd <path>', 'Specify the execution context root directory', process.cwd())
34
+ .option('--fix', 'Enable atomic code updates, structural file pruning, and active type sanitization', true)
35
+ .option('--no-fix', 'Disable direct file manipulation modifications (dry-run reporting mode)')
36
+ .option('--tsconfig <filename>', 'Specify path to custom layout configurations', 'tsconfig.json')
37
+ .option('--test-command <command>', 'Integrated continuous safety test validation script execution path', 'npm test')
38
+ .option('--workspace', 'Enable high-density workspace workspace/monorepo cluster mesh evaluation parsing', false)
39
+ .option('--verbose', 'Toggle expanded trace telemetry for debug operational diagnostics', false)
40
+ .option('-y, --yes', 'Skip confirmation prompts and execute planned structural modifications automatically', false);
41
+
42
+ program.parse(process.argv);
43
+ const options = program.opts();
44
+
45
+ console.log(ansis.bold.green(`\n📦 pkg-scaffold v${packageJsonContent.version || '3.0.0'} Engine Activation`));
46
+ console.log(ansis.dim('------------------------------------------------------------'));
47
+ console.log(`${ansis.bold('Target Workspace Root :')} ${ansis.blue(path.resolve(options.cwd))}`);
48
+ console.log(`${ansis.bold('Refactoring Mode :')} ${options.fix ? ansis.yellow('Active Fixing & Self-Healing Enabled') : ansis.gray('Dry-Run Reporting Only')}`);
49
+ console.log(`${ansis.bold('Validation Sandbox :')} ${ansis.magenta(options.testCommand)}`);
50
+ console.log(ansis.dim('------------------------------------------------------------\n'));
51
+
52
+ const engineModulePath = path.resolve(__dirname, '../src/EngineContext.js');
53
+
54
+ try {
55
+ await fs.access(engineModulePath);
56
+ } catch {
57
+ console.error(ansis.red(`🚨 Execution Fault: Core engine architecture files missing. Ensure src/ directory layout is fully generated.`));
58
+ process.exit(1);
59
+ }
60
+
61
+ // Lazy load execution context wrapper to align with domain initialization
62
+ const { RefactoringEngine } = await import('../src/index.js');
63
+
64
+ if (!RefactoringEngine) {
65
+ console.error(ansis.red('🚨 Architecture Boundary Error: RefactoringEngine could not be resolved from code topology channels.'));
66
+ process.exit(1);
67
+ }
68
+
69
+ // Ensure cwd is always an absolute path regardless of how it was passed (e.g., '--cwd .')
70
+ const engine = new RefactoringEngine({
71
+ cwd: path.resolve(options.cwd),
72
+ autoFix: options.fix,
73
+ tsconfig: options.tsconfig,
74
+ testCommand: options.testCommand,
75
+ workspace: options.workspace,
76
+ verbose: options.verbose,
77
+ skipConfirm: options.yes
78
+ });
79
+
80
+ await engine.run();
81
+
82
+ console.log(ansis.bold.green('\n✨ Core cycle execution completed successfully. Structural layout is clean.'));
83
+ process.exit(0);
84
+
85
+ } catch (criticalBootError) {
86
+ console.error(ansis.bold.red(`\n🚨 Critical Lifecycle Boot Instability: ${criticalBootError.message}`));
87
+ if (criticalBootError.stack) {
88
+ console.error(ansis.dim(criticalBootError.stack));
89
+ }
90
+ process.exit(1);
91
+ }
92
+ }
93
+
94
+ bootstrap();
package/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "pkg-scaffold",
3
- "version": "2.3.0",
4
- "description": "Zero-config workspace initializer with advanced dependency intelligence: detects ghost dependencies (used but undeclared), orphaned packages (declared but unused), unused imports with file locations, deprecated packages, hardcoded secrets, and more.",
3
+ "version": "3.0.0",
4
+ "description": "An advanced, AST-driven dependency resolution, refactoring, and self-healing engine.",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "bin": {
8
- "pkg-scaffold": "./index.js"
8
+ "pkg-scaffold": "./bin/cli.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node bin/cli.js",
12
+ "test": "echo \"Error: no test specified\" && exit 0",
13
+ "test:stability": "npm run test"
9
14
  },
10
15
  "keywords": [
11
16
  "scaffold",
@@ -35,8 +40,15 @@
35
40
  },
36
41
  "homepage": "https://github.com/DreamLongYT/pkg-scaffold#readme",
37
42
  "dependencies": {
38
- "enhanced-resolve": "^5.24.0",
39
- "npm-deprecated-check": "^1.4.0",
40
- "typescript": "^6.0.3"
43
+ "ansis": "^3.0.0",
44
+ "commander": "^12.0.0",
45
+ "enhanced-resolve": "^5.16.0",
46
+ "execa": "^8.0.1",
47
+ "ramda": "^0.29.1",
48
+ "typescript": "^5.4.5",
49
+ "yocto-spinner": "^0.1.0"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
41
53
  }
42
54
  }
@@ -0,0 +1,287 @@
1
+ /**
2
+ * ============================================================================
3
+ * 📦 pkg-scaffold v3.0.0: Enterprise In-Memory Codebase State Manifest
4
+ * ============================================================================
5
+ * Implements a high-density, centralized graph database context for tracking
6
+ * software engineering debt, dependencies, types, and vulnerabilities.
7
+ */
8
+
9
+ import path from 'path';
10
+ import fs from 'fs/promises';
11
+
12
+ /**
13
+ * High-Fidelity Graph Element Node representing a single file asset boundary.
14
+ * @scaffold-suppress GraphNode
15
+ */
16
+ export class GraphNode {
17
+ constructor(filePath) {
18
+ this.filePath = path.normalize(filePath);
19
+ this.contentHash = '';
20
+ this.isLibraryEntry = false;
21
+ this.isFrameworkContract = false;
22
+ this.scriptKind = 0; // Ambient enum mapping
23
+
24
+ // Explicit and Computed Dynamic Syntax Boundaries
25
+ this.explicitImports = new Set();
26
+ this.dynamicImports = new Set();
27
+ this.importedSymbols = new Set(); // Format: 'specifier:symbol' or 'specifier:*'
28
+
29
+ // Internal API Exposed Interfaces (Symbol Name -> ExportMetadata)
30
+ this.internalExports = new Map();
31
+ this.typeOnlyExports = new Set();
32
+
33
+ // Semantic Reference Verification Registries
34
+ this.instantiatedIdentifiers = new Set();
35
+ this.rawStringReferences = new Set();
36
+ this.propertyAccessChains = new Set();
37
+
38
+ // Dependency Mesh Connection Maps
39
+ this.incomingEdges = new Set(); // Set of absolute filePaths depending on this component
40
+ this.outgoingEdges = new Set(); // Set of absolute internal filePaths this component calls
41
+
42
+ // Security & Compliance Anomaly Matrices
43
+ this.securityThreats = [];
44
+ this.calculatedDynamicImports = [];
45
+ this.localSuppressedRules = new Set();
46
+
47
+ // Detailed AST Location Diagnostics (Symbol -> Structural Location Mapping)
48
+ this.symbolSourceLocations = new Map(); // Symbol -> { line: number, column: number, length: number }
49
+ }
50
+
51
+ /**
52
+ * Evaluates if a specific exposed symbol token is utilized by any incoming edges.
53
+ * Leverages precise syntax identity collections.
54
+ */
55
+ isSymbolReferencedExternally(symbolName, projectGraph) {
56
+ if (this.isLibraryEntry) return true;
57
+
58
+ for (const parentPath of this.incomingEdges) {
59
+ const parentNode = projectGraph.get(parentPath);
60
+ if (!parentNode) continue;
61
+
62
+ // Direct identity reference check
63
+ if (parentNode.instantiatedIdentifiers.has(symbolName)) return true;
64
+
65
+ // Property lookup reference checks (e.g., config.databaseUrl)
66
+ for (const accessChain of parentNode.propertyAccessChains) {
67
+ if (accessChain.endsWith(`.${symbolName}`) || accessChain.includes(`.${symbolName}.`)) {
68
+ return true;
69
+ }
70
+ }
71
+
72
+ // Safe fallback lookup inside string reference caches (e.g., obj['databaseUrl'])
73
+ if (parentNode.rawStringReferences.has(symbolName)) return true;
74
+ }
75
+
76
+ return false;
77
+ }
78
+
79
+ /**
80
+ * Compiles complete localized diagnostic telemetry tracking metrics for this node instance.
81
+ */
82
+ compileNodeTelemetry() {
83
+ return {
84
+ path: this.filePath,
85
+ totalExplicitImportsCount: this.explicitImports.size,
86
+ totalExposedExportsCount: this.internalExports.size,
87
+ incomingDependenciesCount: this.incomingEdges.size,
88
+ outgoingDependenciesCount: this.outgoingEdges.size,
89
+ isDanglingOrphan: this.incomingEdges.size === 0 && !this.isLibraryEntry,
90
+ trackedThreatsCount: this.securityThreats.length
91
+ };
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Enterprise Engine Run State Registry & Suppression Context Matrix
97
+ */
98
+ export class EngineContext {
99
+ constructor(options = {}) {
100
+ this.cwd = path.normalize(options.cwd || process.cwd());
101
+ this.cacheDir = path.join(this.cwd, '.scaffold-cache');
102
+ this.ignoreFilePath = path.join(this.cwd, '.scaffold-ignore');
103
+ this.tsconfigFilename = options.tsconfig || 'tsconfig.json';
104
+ this.testCommand = options.testCommand || 'npm test';
105
+
106
+ this.allowAutoFix = options.autoFix ?? true;
107
+ this.isWorkspaceEnabled = options.workspace ?? false;
108
+ this.verbose = options.verbose ?? false;
109
+ this.skipConfirm = options.skipConfirm ?? false;
110
+
111
+ // Core Memory Repositories
112
+ this.graph = new Map(); // Absolute File Path -> GraphNode
113
+ this.registryHashes = new Map(); // Package Name -> Secure Lockfile Signature String
114
+ this.globallyIgnoredSymbols = new Set();
115
+ this.globallyIgnoredPaths = [];
116
+ this.monorepoPackageRoots = new Set();
117
+
118
+ // Structural Heuristic Verification Metrics Tracker
119
+ this.metrics = {
120
+ startTime: 0,
121
+ endTime: 0,
122
+ totalFilesScanned: 0,
123
+ cacheHits: 0,
124
+ cacheMisses: 0,
125
+ prunedFilesCount: 0,
126
+ prunedExportsCount: 0,
127
+ totalSymbolsAnalyzed: 0,
128
+ securityVulnerabilitiesMitigated: 0
129
+ };
130
+ }
131
+
132
+ /**
133
+ * Initializes baseline context options, directory footprints, and suppression maps.
134
+ */
135
+ async initialize() {
136
+ this.metrics.startTime = Date.now();
137
+ await fs.mkdir(this.cacheDir, { recursive: true });
138
+ await this.compileIgnoreConfigurations();
139
+ }
140
+
141
+ /**
142
+ * Parses .scaffold-ignore layers using precise token segment matching
143
+ * instead of high-risk loose regex blocks.
144
+ */
145
+ async compileIgnoreConfigurations() {
146
+ try {
147
+ const content = await fs.readFile(this.ignoreFilePath, 'utf8');
148
+ const lines = content.split('\n');
149
+
150
+ for (let line of lines) {
151
+ line = line.trim();
152
+ if (!line || line.startsWith('#')) continue;
153
+
154
+ if (line.startsWith('export:')) {
155
+ const symbolToken = line.replace('export:', '').trim();
156
+ this.globallyIgnoredSymbols.add(symbolToken);
157
+ } else if (line.startsWith('path:')) {
158
+ const pathToken = line.replace('path:', '').trim();
159
+ this.globallyIgnoredPaths.push(path.normalize(pathToken));
160
+ } else {
161
+ // Standard structural path rule fallback
162
+ this.globallyIgnoredPaths.push(path.normalize(line));
163
+ }
164
+ }
165
+ } catch {
166
+ // Configuration optionally omitted; proceed with default execution flags
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Allocates or resolves a unified GraphNode reference inside our memory map index.
172
+ */
173
+ createNode(absoluteFilePath) {
174
+ const normalizedPath = path.normalize(absoluteFilePath);
175
+ if (this.graph.has(normalizedPath)) {
176
+ return this.graph.get(normalizedPath);
177
+ }
178
+ const node = new GraphNode(normalizedPath);
179
+ this.graph.set(normalizedPath, node);
180
+ return node;
181
+ }
182
+
183
+ /**
184
+ * Checks if an absolute file token path matches configuration ignore directives.
185
+ * Evaluates sub-path sequences exactly to prevent regular expression parsing drops.
186
+ */
187
+ isPathIgnored(absoluteFilePath) {
188
+ const relativeText = path.relative(this.cwd, absoluteFilePath);
189
+
190
+ for (const ignoredTarget of this.globallyIgnoredPaths) {
191
+ if (relativeText === ignoredTarget || relativeText.startsWith(path.join(ignoredTarget, path.sep))) {
192
+ return true;
193
+ }
194
+ // Handle explicit wildcard terminal indicators
195
+ if (ignoredTarget.endsWith('*')) {
196
+ const baseSegment = ignoredTarget.slice(0, -1);
197
+ if (relativeText.startsWith(baseSegment)) return true;
198
+ }
199
+ }
200
+ return false;
201
+ }
202
+
203
+ /**
204
+ * Processes the entire active dependency map to compile structural issue indices.
205
+ * Evaluates orphaned components, dead exports, and supply-chain threats.
206
+ */
207
+ generateSummaryReport() {
208
+ this.metrics.endTime = Date.now();
209
+ const durationSeconds = ((this.metrics.endTime - this.metrics.startTime) / 1000).toFixed(2);
210
+
211
+ const summary = {
212
+ executionDuration: `${durationSeconds}s`,
213
+ totalFilesProcessed: this.metrics.totalFilesScanned,
214
+ graphCacheOptimization: {
215
+ hits: this.metrics.cacheHits,
216
+ misses: this.metrics.cacheMisses,
217
+ ratio: this.metrics.totalFilesScanned > 0
218
+ ? `${((this.metrics.cacheHits / this.metrics.totalFilesScanned) * 100).toFixed(1)}%`
219
+ : '0%'
220
+ },
221
+ structuralIssuesDetected: {
222
+ deadFiles: [],
223
+ deadExports: [],
224
+ securityThreats: []
225
+ },
226
+ modificationsExecuted: {
227
+ filesUnlinked: this.metrics.prunedFilesCount,
228
+ exportsStripped: this.metrics.prunedExportsCount
229
+ }
230
+ };
231
+
232
+ for (const [filePath, node] of this.graph.entries()) {
233
+ // Skip package control files from standard structural dead-code checks
234
+ if (filePath.endsWith('package.json')) continue;
235
+ if (this.isPathIgnored(filePath)) continue;
236
+
237
+ const relativePath = path.relative(this.cwd, filePath);
238
+
239
+ // Category A: Completely orphaned components (no references, not library/framework entries)
240
+ // A file with ANY @scaffold-suppress directive is considered intentionally retained and must
241
+ // never be flagged as orphaned, even if no other file imports it directly.
242
+ const fileHasSuppressDirective = node.localSuppressedRules.size > 0;
243
+ if (node.incomingEdges.size === 0 && !node.isLibraryEntry && !node.isFrameworkContract && !fileHasSuppressDirective) {
244
+ summary.structuralIssuesDetected.deadFiles.push(relativePath);
245
+ continue; // An orphaned file implies all internal sub-exports are dead; skip sub-checks
246
+ }
247
+
248
+ // Category B: Dead Named Exports inside active files
249
+ for (const [exportName, meta] of node.internalExports.entries()) {
250
+ this.metrics.totalSymbolsAnalyzed++;
251
+
252
+ // Skip entry configurations, global suppresses, and type-suppressed symbols
253
+ if (exportName === 'default' ||
254
+ this.globallyIgnoredSymbols.has(exportName) ||
255
+ node.localSuppressedRules.has(exportName)) {
256
+ continue;
257
+ }
258
+
259
+ if (!node.isSymbolReferencedExternally(exportName, this.graph)) {
260
+ const diagnosticLocation = node.symbolSourceLocations.get(exportName) || { line: 1, column: 1 };
261
+ summary.structuralIssuesDetected.deadExports.push({
262
+ file: relativePath,
263
+ symbol: exportName,
264
+ type: meta.type || 'named',
265
+ line: diagnosticLocation.line,
266
+ column: diagnosticLocation.column
267
+ });
268
+ }
269
+ }
270
+
271
+ // Category C: High-Entropy Password / Key Hardcode Vulnerabilities
272
+ if (node.securityThreats && node.securityThreats.length > 0) {
273
+ node.securityThreats.forEach(threat => {
274
+ summary.structuralIssuesDetected.securityThreats.push({
275
+ file: relativePath,
276
+ identifier: threat.variableKey,
277
+ riskCode: threat.riskCode || 'HIGH_RISK_SECRET_LEAK',
278
+ entropy: threat.entropyValue,
279
+ line: threat.line || 1
280
+ });
281
+ });
282
+ }
283
+ }
284
+
285
+ return summary;
286
+ }
287
+ }