pkg-scaffold 2.2.0 โ†’ 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,177 @@
1
+ import ts from 'typescript';
2
+ import fs from 'fs/promises';
3
+
4
+ /**
5
+ * Enterprise Wildcard Optimization & Flattening Layer for Barrel Operations
6
+ * Traces unreferenced paths through redistribution entries.
7
+ */
8
+ export class BarrelParser {
9
+ constructor(context, resolver) {
10
+ this.context = context;
11
+ this.resolver = resolver;
12
+ this.cachedSpecifications = new Map();
13
+ }
14
+
15
+ /**
16
+ * Compiles the structural export layout for a specific index or barrel target.
17
+ * @param {string} filePath - Absolute path to on-disk target element
18
+ */
19
+ async parseBarrelSpecification(filePath) {
20
+ if (this.cachedSpecifications.has(filePath)) {
21
+ return this.cachedSpecifications.get(filePath);
22
+ }
23
+
24
+ const specification = {
25
+ isBarrelInstance: false,
26
+ wildcardExports: new Set(), // export * from './module';
27
+ namespacedWildcardExports: new Map(), // export * as Utils from './module';
28
+ forwardedNamedExports: new Map(), // export { token as alias } from './module';
29
+ declaredLocalExports: new Set() // export const a = 1;
30
+ };
31
+
32
+ try {
33
+ const code = await fs.readFile(filePath, 'utf8');
34
+ const sourceFile = ts.createSourceFile(filePath, code, ts.ScriptTarget.Latest, true);
35
+
36
+ this.harvestExportSignatures(sourceFile, specification);
37
+
38
+ if (specification.wildcardExports.size > 0 ||
39
+ specification.namespacedWildcardExports.size > 0 ||
40
+ specification.forwardedNamedExports.size > 0) {
41
+ specification.isBarrelInstance = true;
42
+ }
43
+
44
+ this.cachedSpecifications.set(filePath, specification);
45
+ return specification;
46
+ } catch {
47
+ return specification; // Error state defaults to safe boundaries layout manifest
48
+ }
49
+ }
50
+
51
+ harvestExportSignatures(node, spec) {
52
+ if (!node) return;
53
+
54
+ switch (node.kind) {
55
+ case ts.SyntaxKind.ExportDeclaration: {
56
+ const targetSpecifier = node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)
57
+ ? node.moduleSpecifier.text
58
+ : null;
59
+
60
+ if (targetSpecifier) {
61
+ if (!node.exportClause) {
62
+ // Standard Wildcard Transfer: export * from './module';
63
+ spec.wildcardExports.add(targetSpecifier);
64
+ } else if (ts.isNamespaceExport(node.exportClause)) {
65
+ // Namespaced Wildcard Transfer: export * as Core from './module';
66
+ const namespaceAlias = node.exportClause.name.text;
67
+ spec.namespacedWildcardExports.set(namespaceAlias, targetSpecifier);
68
+ } else if (ts.isNamedExports(node.exportClause)) {
69
+ // Selective Re-export Forwarding: export { x, y as z } from './module';
70
+ node.exportClause.elements.forEach(element => {
71
+ const originalSymbol = element.propertyName ? element.propertyName.text : element.name.text;
72
+ const exposedAlias = element.name.text;
73
+ spec.forwardedNamedExports.set(exposedAlias, {
74
+ targetModule: targetSpecifier,
75
+ sourceSymbol: originalSymbol
76
+ });
77
+ });
78
+ }
79
+ }
80
+ break;
81
+ }
82
+
83
+ // Track items declared directly within the file boundary
84
+ case ts.SyntaxKind.FunctionDeclaration:
85
+ case ts.SyntaxKind.ClassDeclaration:
86
+ case ts.SyntaxKind.InterfaceDeclaration:
87
+ case ts.SyntaxKind.TypeAliasDeclaration:
88
+ case ts.SyntaxKind.EnumDeclaration: {
89
+ if (node.modifiers && node.modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword)) {
90
+ if (node.name && ts.isIdentifier(node.name)) {
91
+ spec.declaredLocalExports.add(node.name.text);
92
+ }
93
+ }
94
+ break;
95
+ }
96
+
97
+ case ts.SyntaxKind.VariableStatement: {
98
+ if (node.modifiers && node.modifiers.some(m => m.kind === ts.SyntaxKind.ExportKeyword)) {
99
+ node.declarationList.declarations.forEach(decl => {
100
+ if (ts.isIdentifier(decl.name)) {
101
+ spec.declaredLocalExports.add(decl.name.text);
102
+ }
103
+ });
104
+ }
105
+ break;
106
+ }
107
+ }
108
+
109
+ ts.forEachChild(node, child => this.harvestExportSignatures(child, spec));
110
+ }
111
+
112
+ /**
113
+ * Challenge #3 Resolution Logic. Unwraps nested redistribution links to find origin source nodes.
114
+ * @param {string} contextFilePath - Current position filename vector pointer
115
+ * @param {string} targetSymbolName - Targeted semantic variable signature name
116
+ * @param {Map} activeProjectGraph - Global active module maps directory registry
117
+ * @param {Set} [protectionStack] - Avoids cyclic validation traps inside self-referencing links
118
+ */
119
+ async determineSymbolDeclarationOrigin(contextFilePath, targetSymbolName, activeProjectGraph, protectionStack = new Set()) {
120
+ if (protectionStack.has(contextFilePath)) {
121
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
122
+ }
123
+ protectionStack.add(contextFilePath);
124
+
125
+ const spec = await this.parseBarrelSpecification(contextFilePath);
126
+ if (!spec.isBarrelInstance) {
127
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
128
+ }
129
+
130
+ // Rule A: Settle boundary immediately if local declaration matches token signature name
131
+ if (spec.declaredLocalExports.has(targetSymbolName)) {
132
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
133
+ }
134
+
135
+ // Rule B: Evaluate explicit named re-export mappings
136
+ if (spec.forwardedNamedExports.has(targetSymbolName)) {
137
+ const routingRule = spec.forwardedNamedExports.get(targetSymbolName);
138
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, routingRule.targetModule);
139
+ return this.determineSymbolDeclarationOrigin(fullyResolvedPath, routingRule.sourceSymbol, activeProjectGraph, protectionStack);
140
+ }
141
+
142
+ // Rule C: Evaluate structural namespace alias groupings
143
+ if (spec.namespacedWildcardExports.has(targetSymbolName)) {
144
+ const relativeModule = spec.namespacedWildcardExports.get(targetSymbolName);
145
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativeModule);
146
+ return { originFile: fullyResolvedPath, originSymbol: '*' };
147
+ }
148
+
149
+ // Rule D: Sweep through anonymous star re-exports vectors
150
+ for (const relativePath of spec.wildcardExports) {
151
+ const fullyResolvedPath = this.resolver.resolveModulePath(contextFilePath, relativePath);
152
+
153
+ // Look inside the graph metadata map configuration to verify child target availability
154
+ const targetSubSpec = await this.parseBarrelSpecification(fullyResolvedPath);
155
+
156
+ if (targetSubSpec.declaredLocalExports.has(targetSymbolName) ||
157
+ targetSubSpec.forwardedNamedExports.has(targetSymbolName)) {
158
+ return this.determineSymbolDeclarationOrigin(fullyResolvedPath, targetSymbolName, activeProjectGraph, protectionStack);
159
+ }
160
+
161
+ // Dynamic recursive trace for multi-tier nested barrel file layouts
162
+ if (targetSubSpec.isBarrelInstance) {
163
+ const continuousResolutionTrace = await this.determineSymbolDeclarationOrigin(
164
+ fullyResolvedPath,
165
+ targetSymbolName,
166
+ activeProjectGraph,
167
+ protectionStack
168
+ );
169
+ if (continuousResolutionTrace && continuousResolutionTrace.originFile !== fullyResolvedPath) {
170
+ return continuousResolutionTrace;
171
+ }
172
+ }
173
+ }
174
+
175
+ return { originFile: contextFilePath, originSymbol: targetSymbolName };
176
+ }
177
+ }
@@ -0,0 +1,154 @@
1
+ import path from 'path';
2
+ import fs from 'fs/promises';
3
+
4
+ /**
5
+ * Ecosystem Entry Point Manifest & Dynamic Framework Router Heuristic Validator
6
+ * Intercepts implicit conventions to handle cases where direct import statements are absent.
7
+ */
8
+ export class MagicDetector {
9
+ constructor(context) {
10
+ this.context = context;
11
+ this.manifestSchemaRules = this.compileEcosystemSchemaMatrices();
12
+ }
13
+
14
+ /**
15
+ * Compiles explicit layout definitions to handle various web development environments.
16
+ */
17
+ compileEcosystemSchemaMatrices() {
18
+ return {
19
+ nextjs: {
20
+ configFiles: ['next.config.js', 'next.config.mjs', 'next.config.ts'],
21
+ routePatterns: [
22
+ /\/pages\/api\//,
23
+ /\/pages\/[a-zA-Z0-9_\-\[\]]+/i,
24
+ /\/app\/([\w\-\[\]]+\/)+(page|route|layout|loading|error|not-found)\.(ts|tsx|js|jsx)$/
25
+ ],
26
+ requiredSystemContracts: ['default', 'getServerSideProps', 'getStaticProps', 'getStaticPaths', 'generateMetadata', 'middleware']
27
+ },
28
+ nuxt: {
29
+ configFiles: ['nuxt.config.js', 'nuxt.config.ts'],
30
+ routePatterns: [
31
+ /\/pages\//,
32
+ /\/server\/(api|routes|middleware)\//,
33
+ /\/components\/[a-zA-Z0-9_\-\/]+\.vue$/
34
+ ],
35
+ requiredSystemContracts: ['default']
36
+ },
37
+ remix: {
38
+ configFiles: ['remix.config.js', 'vite.config.js', 'vite.config.ts'],
39
+ routePatterns: [
40
+ /\/app\/routes\//,
41
+ /\/app\/root\.(tsx|jsx)$/
42
+ ],
43
+ requiredSystemContracts: ['default', 'loader', 'action', 'meta', 'links']
44
+ },
45
+ sveltekit: {
46
+ configFiles: ['svelte.config.js', 'vite.config.ts'],
47
+ routePatterns: [
48
+ /\+page\.(svelte|ts|js)$/,
49
+ /\+page\.server\.(ts|js)$/,
50
+ /\+layout\.(svelte|ts|js)$/,
51
+ /\+server\.(ts|js)$/
52
+ ],
53
+ requiredSystemContracts: ['load', 'actions', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']
54
+ },
55
+ astro: {
56
+ configFiles: ['astro.config.mjs', 'astro.config.cjs', 'astro.config.ts'],
57
+ routePatterns: [
58
+ /\/src\/pages\/.*\.astro$/,
59
+ /\/src\/pages\/.*\.(ts|js)$/
60
+ ],
61
+ requiredSystemContracts: ['default', 'getStaticPaths']
62
+ }
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Audits the project context to map active micro-framework ecosystems.
68
+ * @param {string} baseContextDirectory - Root file workspace context execution vector path
69
+ */
70
+ async identifyActiveProjectEcosystems(baseContextDirectory) {
71
+ const activeFrameworkFlags = [];
72
+
73
+ for (const [frameworkKey, criteria] of Object.entries(this.manifestSchemaRules)) {
74
+ for (const configFile of criteria.configFiles) {
75
+ try {
76
+ await fs.access(path.join(baseContextDirectory, configFile));
77
+ activeFrameworkFlags.push(frameworkKey);
78
+ break; // Stop scanning once config criteria is found
79
+ } catch {
80
+ // File path criteria absent; proceed to standard verification loops
81
+ }
82
+ }
83
+ }
84
+
85
+ // Universal infrastructure overrides (testing platforms and common bundlers)
86
+ activeFrameworkFlags.push('universal-tooling-vectors');
87
+ return activeFrameworkFlags;
88
+ }
89
+
90
+ /**
91
+ * Assesses if a file path acts as an implicit route entry point.
92
+ */
93
+ isImplicitlyRequiredByEcosystem(absolutePath, activeFrameworks) {
94
+ const normalizedSystemPath = absolutePath.replace(/\\/g, '/');
95
+
96
+ for (const framework of activeFrameworks) {
97
+ const frameworkRules = this.manifestSchemaRules[framework];
98
+ if (!frameworkRules) continue;
99
+
100
+ const matchesPattern = frameworkRules.routePatterns.some(regex => regex.test(normalizedSystemPath));
101
+ if (matchesPattern) return true;
102
+ }
103
+
104
+ // Apply baseline platform rules (Test suites, lint parameters, continuous integration files)
105
+ if (this.isCoreToolingSuiteElement(normalizedSystemPath)) {
106
+ return true;
107
+ }
108
+
109
+ return false;
110
+ }
111
+
112
+ isCoreToolingSuiteElement(normalizedPath) {
113
+ // Testing and execution matrices rules configuration keys
114
+ if (/\.(test|spec|e2e|cy)\.(js|ts|tsx|jsx|stories\.tsx|stories\.ts)$/i.test(normalizedPath)) return true;
115
+
116
+ // Testing tools and structural environment frameworks configuration keys
117
+ const testEnvironments = [
118
+ 'jest.config.', 'vitest.config.', 'playwright.config.', 'cypress.config.',
119
+ 'webpack.config.', 'vite.config.', 'rollup.config.', 'tailwind.config.',
120
+ '.eslintrc.', 'prettier.config.', '.postcssrc.', 'postcss.config.'
121
+ ];
122
+
123
+ return testEnvironments.some(matchPattern => normalizedPath.includes(matchPattern));
124
+ }
125
+
126
+ /**
127
+ * Challenge #4 Framework Overrides. Protects interface boundaries from false positive report flags.
128
+ */
129
+ injectVirtualConsumerEdges(filePath, fileNode, activeFrameworks) {
130
+ if (!this.isImplicitlyRequiredByEcosystem(filePath, activeFrameworks)) return;
131
+
132
+ // Retain entry point elements within memory to keep verification safe
133
+ fileNode.isLibraryEntry = true;
134
+
135
+ // Apply dynamic exports coverage metrics based on active platform contracts
136
+ const normalizedPath = filePath.replace(/\\/g, '/');
137
+
138
+ for (const framework of activeFrameworks) {
139
+ const frameworkRules = this.manifestSchemaRules[framework];
140
+ if (!frameworkRules) continue;
141
+
142
+ // If the file path matches the active framework schema, protect its interface keywords
143
+ const appliesToFramework = frameworkRules.routePatterns.some(regex => regex.test(normalizedPath));
144
+ if (appliesToFramework) {
145
+ frameworkRules.requiredSystemContracts.forEach(contractMethodToken => {
146
+ if (fileNode.internalExports.has(contractMethodToken)) {
147
+ // Emulate active local reference linkages to protect the export
148
+ fileNode.instantiatedIdentifiers.add(contractMethodToken);
149
+ }
150
+ });
151
+ }
152
+ }
153
+ }
154
+ }
@@ -0,0 +1,160 @@
1
+ import { execSync } from 'child_process';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Ephemeral Git Sandbox & Version Control Islolation Gateway
6
+ * Manages atomic branch switching, working-tree stashing, and systemic rollbacks.
7
+ */
8
+ export class GitSandbox {
9
+ constructor(context) {
10
+ this.context = context;
11
+ this.originalBranch = null;
12
+ this.sandboxBranch = null;
13
+ this.hasStashedChanges = false;
14
+ this.isGitRepository = false;
15
+ }
16
+
17
+ /**
18
+ * Validates the active environment and isolates the working directory.
19
+ */
20
+ async establishIsolationCheckpoint() {
21
+ this.verifyGitRepositoryPresence();
22
+ if (!this.isGitRepository) return;
23
+
24
+ try {
25
+ // Capture the current branch name
26
+ this.originalBranch = execSync('git rev-parse --abbrev-ref HEAD', {
27
+ cwd: this.context.cwd,
28
+ encoding: 'utf8'
29
+ }).trim();
30
+
31
+ // Check for uncommitted working directory changes
32
+ const statusOutput = execSync('git status --porcelain', {
33
+ cwd: this.context.cwd,
34
+ encoding: 'utf8'
35
+ }).trim();
36
+
37
+ if (statusOutput.length > 0) {
38
+ if (this.context.verbose) {
39
+ console.log('๐Ÿ“ฆ Working tree contains uncommitted changes. Stashing before running pipeline...');
40
+ }
41
+ execSync('git stash save "pkg-scaffold: Ephemeral Checkpoint Stash"', {
42
+ cwd: this.context.cwd,
43
+ stdio: 'ignore'
44
+ });
45
+ this.hasStashedChanges = true;
46
+ }
47
+
48
+ // Generate an isolated tracking branch name
49
+ this.sandboxBranch = `scaffold-heal-${Date.now()}`;
50
+ execSync(`git checkout -b ${this.sandboxBranch}`, {
51
+ cwd: this.context.cwd,
52
+ stdio: 'ignore'
53
+ });
54
+
55
+ if (this.context.verbose) {
56
+ console.log(`๐ŸŒฟ Isolated sandbox branch successfully initialized: [${this.sandboxBranch}]`);
57
+ }
58
+ } catch (error) {
59
+ throw new Error(`Git Sandbox separation failure: ${error.message}`);
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Commits all modifications within the sandbox branch for validation testing.
65
+ */
66
+ async stageAndCheckpointChanges(commitMessage = 'refactor(scaffold): apply structural optimizations') {
67
+ if (!this.isGitRepository) return;
68
+ this.assertActiveIsolation();
69
+
70
+ try {
71
+ execSync('git add .', { cwd: this.context.cwd, stdio: 'ignore' });
72
+
73
+ // Check if any mutations were actually staged
74
+ const diffIndex = execSync('git diff --cached --name-only', {
75
+ cwd: this.context.cwd,
76
+ encoding: 'utf8'
77
+ }).trim();
78
+
79
+ if (diffIndex.length === 0) return; // No modifications to verify
80
+
81
+ execSync(`git commit -m "${commitMessage}" --no-verify`, {
82
+ cwd: this.context.cwd,
83
+ stdio: 'ignore'
84
+ });
85
+ } catch (error) {
86
+ throw new Error(`Failed to stage changes inside the sandbox: ${error.message}`);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Merges modifications back into the mainline branch if all validation test suites pass.
92
+ */
93
+ async acceptAndMergeOptimizations() {
94
+ if (!this.isGitRepository) return;
95
+ this.assertActiveIsolation();
96
+
97
+ try {
98
+ // Return to the original project branch boundary
99
+ execSync(`git checkout ${this.originalBranch}`, { cwd: this.context.cwd, stdio: 'ignore' });
100
+
101
+ // Merge the verified changes without creating a fast-forward bottleneck
102
+ execSync(`git merge --squash ${this.sandboxBranch}`, { cwd: this.context.cwd, stdio: 'ignore' });
103
+ execSync('git commit -m "chore(refactor): apply verified dead-code removals" --no-verify', {
104
+ cwd: this.context.cwd,
105
+ stdio: 'ignore'
106
+ });
107
+
108
+ // Purge the temporary branch tracking reference
109
+ execSync(`git branch -D ${this.sandboxBranch}`, { cwd: this.context.cwd, stdio: 'ignore' });
110
+ this.restorePreviousWorkingState();
111
+ } catch (error) {
112
+ throw new Error(`Failed to merge sandbox modifications into mainline branch: ${error.message}`);
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Reverts all disk changes instantly if testing suites flag an error.
118
+ */
119
+ async rejectAndAbortOptimizations() {
120
+ if (!this.isGitRepository) return;
121
+ if (!this.sandboxBranch) return;
122
+
123
+ try {
124
+ if (this.context.verbose) {
125
+ console.log('๐Ÿ”„ Aborting transaction loop. Resetting file systems...');
126
+ }
127
+
128
+ execSync('git add . && git reset --hard HEAD', { cwd: this.context.cwd, stdio: 'ignore' });
129
+ execSync(`git checkout ${this.originalBranch}`, { cwd: this.context.cwd, stdio: 'ignore' });
130
+ execSync(`git branch -D ${this.sandboxBranch}`, { cwd: this.context.cwd, stdio: 'ignore' });
131
+
132
+ this.restorePreviousWorkingState();
133
+ } catch (error) {
134
+ console.error(`๐Ÿšจ Critical Recovery Error: Failed to drop sandbox branch cleanly: ${error.message}`);
135
+ }
136
+ }
137
+
138
+ restorePreviousWorkingState() {
139
+ if (this.hasStashedChanges) {
140
+ execSync('git stash pop', { cwd: this.context.cwd, stdio: 'ignore' });
141
+ this.hasStashedChanges = false;
142
+ }
143
+ this.sandboxBranch = null;
144
+ }
145
+
146
+ verifyGitRepositoryPresence() {
147
+ try {
148
+ execSync('git rev-parse --is-inside-work-tree', { cwd: this.context.cwd, stdio: 'ignore' });
149
+ this.isGitRepository = true;
150
+ } catch {
151
+ this.isGitRepository = false;
152
+ }
153
+ }
154
+
155
+ assertActiveIsolation() {
156
+ if (!this.sandboxBranch) {
157
+ throw new Error('Git Sandbox operation error: No active sandbox tracking context exists.');
158
+ }
159
+ }
160
+ }
@@ -0,0 +1,150 @@
1
+ import { spawn } from 'child_process';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Self-Healing Test Orchestration & Regression Scanner
6
+ * Runs validation suites, intercepts stack traces, and controls transaction rollbacks.
7
+ */
8
+ export class SelfHealer {
9
+ constructor(context, transactionManager, gitSandbox) {
10
+ this.context = context;
11
+ this.transactionManager = transactionManager;
12
+ this.gitSandbox = gitSandbox;
13
+ this.executionTimeout = 45000; // 45-second execution timeout wall
14
+ }
15
+
16
+ /**
17
+ * Validates the stability of staged code changes by running your project's test suite.
18
+ * @param {Function} refactorTask - The function containing code changes to evaluate
19
+ */
20
+ async runSelfHealingLifecycle(refactorTask) {
21
+ console.log('๐Ÿ›ก๏ธ Initializing transaction safety sandbox...');
22
+
23
+ // Step 1: Open the transaction boundaries
24
+ await this.gitSandbox.establishIsolationCheckpoint();
25
+ await this.transactionManager.begin();
26
+
27
+ try {
28
+ // Step 2: Execute the codebase pruning transformations
29
+ await refactorTask();
30
+
31
+ // Step 3: Stage changes inside our Git tracking context
32
+ await this.gitSandbox.checkpointChanges();
33
+
34
+ console.log('๐Ÿงช Running testing suites to verify workspace integrity...');
35
+ const validationPassed = await this.verifyProjectHealthStatus();
36
+
37
+ if (validationPassed) {
38
+ console.log('โœจ Build stable. Merging verified code improvements.');
39
+ await this.transactionManager.commit();
40
+ await this.gitSandbox.acceptAndMergeOptimizations();
41
+ return true;
42
+ } else {
43
+ console.warn('โš ๏ธ Regression flagged during validation. Triggering self-healing rollback...');
44
+ await this.revertWorkspaceToSafeState();
45
+ return false;
46
+ }
47
+ } catch (pipelineError) {
48
+ console.error(`๐Ÿšจ Critical Exception Intercepted: ${pipelineError.message}`);
49
+ await this.revertWorkspaceToSafeState();
50
+ return false;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Spawns testing processes to detect exit code alerts or compiler trace metrics.
56
+ * @returns {Promise<boolean>} True if the test suite runs with an exit code of 0
57
+ */
58
+ verifyProjectHealthStatus() {
59
+ return new Promise((resolve) => {
60
+ const commandTokens = this.context.testCommand.split(' ');
61
+ const executionBinary = commandTokens.shift();
62
+
63
+ const processBuffer = [];
64
+ const testProcess = spawn(executionBinary, commandTokens, {
65
+ cwd: this.context.cwd,
66
+ shell: true
67
+ });
68
+
69
+ // Implement an execution timeout monitor to prevent hanging test suites from blocking the pipeline
70
+ const timeoutWatch = setTimeout(() => {
71
+ console.warn('โฑ๏ธ Test execution exceeded timeout limit. Terminating subprocess...');
72
+ testProcess.kill('SIGKILL');
73
+ }, this.executionTimeout);
74
+
75
+ testProcess.stdout.on('data', (data) => {
76
+ processBuffer.push(data);
77
+ if (this.context.verbose) {
78
+ process.stdout.write(data);
79
+ }
80
+ });
81
+
82
+ testProcess.stderr.on('data', (data) => {
83
+ processBuffer.push(data);
84
+ if (this.context.verbose) {
85
+ process.stderr.write(data);
86
+ }
87
+ });
88
+
89
+ testProcess.on('close', (exitCode) => {
90
+ clearTimeout(timeoutWatch);
91
+
92
+ if (exitCode !== 0) {
93
+ const fullConsoleOutput = Buffer.concat(processBuffer).toString('utf8');
94
+ this.diagnoseErrorOutput(fullConsoleOutput);
95
+ resolve(false);
96
+ } else {
97
+ resolve(true);
98
+ }
99
+ });
100
+
101
+ testProcess.on('error', (err) => {
102
+ clearTimeout(timeoutWatch);
103
+ if (this.context.verbose) {
104
+ console.error(`Subprocess execution error: ${err.message}`);
105
+ }
106
+ resolve(false);
107
+ });
108
+ });
109
+ }
110
+
111
+ /**
112
+ * Traces error codes and console log outputs to identify the root cause of a broken build.
113
+ */
114
+ diagnoseErrorOutput(consoleLogOutput) {
115
+ console.log('\n๐Ÿ” [Diagnostics] Reviewing error output...');
116
+
117
+ // Scan for standard TypeScript Compilation errors
118
+ const tsErrorPattern = /error\s+TS(\d+):\s+([\s\S]*?)$/m;
119
+ const tsMatches = consoleLogOutput.match(tsErrorPattern);
120
+
121
+ if (tsMatches) {
122
+ console.error(`โŒ Mapped Type Error Code [TS${tsMatches[1]}]: ${tsMatches[2].trim()}`);
123
+ return;
124
+ }
125
+
126
+ // Scan for missing file imports or runtime resolution exceptions
127
+ const missingModulePattern = /Cannot find module '([^']+)'/i;
128
+ const moduleMatches = consoleLogOutput.match(missingModulePattern);
129
+
130
+ if (moduleMatches) {
131
+ console.error(`โŒ Missing Dependency Reference Pointer: Cannot locate element [${moduleMatches[1]}]`);
132
+ return;
133
+ }
134
+
135
+ console.error('โŒ Test suite execution failed. Check standard console output for details.');
136
+ }
137
+
138
+ /**
139
+ * Automatically executes a rollback event, restoring both file states and Git status.
140
+ */
141
+ async revertWorkspaceToSafeState() {
142
+ try {
143
+ await this.transactionManager.rollback();
144
+ await this.gitSandbox.rejectAndAbortOptimizations();
145
+ console.log('๐Ÿ”„ [Self-Healing] Rollback complete. Original project states restored.');
146
+ } catch (recoveryError) {
147
+ console.error(`๐Ÿšจ Fatal Recovery Error: Failed to restore prior workspace configuration: ${recoveryError.message}`);
148
+ }
149
+ }
150
+ }