xtrm-tools 0.5.21 → 0.5.22

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.
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtrm-cli",
3
- "version": "0.5.21",
3
+ "version": "0.5.22",
4
4
  "description": "Claude Code tools installer (skills, hooks, MCP servers)",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
@@ -7,6 +7,7 @@ import { spawnSync } from 'node:child_process';
7
7
  import { readFileSync, existsSync, writeFileSync, unlinkSync, mkdirSync } from 'node:fs';
8
8
  import { join } from 'node:path';
9
9
  import { resolveSessionId } from './beads-gate-utils.mjs';
10
+ import { logEvent } from './xtrm-logger.mjs';
10
11
 
11
12
  function readInput() {
12
13
  try {
@@ -141,6 +142,17 @@ function main() {
141
142
  writeFileSync(join(xtrmDir, 'statusline-claim'), issueId);
142
143
  } catch { /* non-fatal */ }
143
144
 
145
+ logEvent({
146
+ cwd,
147
+ runtime: 'claude',
148
+ sessionId,
149
+ layer: 'bd',
150
+ kind: 'bd.claimed',
151
+ outcome: 'allow',
152
+ issueId,
153
+ message: `Session ${sessionId} claimed issue ${issueId}`,
154
+ });
155
+
144
156
  process.stdout.write(JSON.stringify({
145
157
  additionalContext: `\n✅ **Beads**: Session \`${sessionId}\` claimed issue \`${issueId}\`.`,
146
158
  }));
@@ -169,6 +181,33 @@ function main() {
169
181
  });
170
182
  }
171
183
 
184
+ // Log bd lifecycle events
185
+ if (closedIssueId) {
186
+ logEvent({
187
+ cwd,
188
+ runtime: 'claude',
189
+ sessionId,
190
+ layer: 'bd',
191
+ kind: 'bd.closed',
192
+ outcome: 'allow',
193
+ issueId: closedIssueId,
194
+ message: `Issue ${closedIssueId} closed`,
195
+ });
196
+ }
197
+ if (commit) {
198
+ logEvent({
199
+ cwd,
200
+ runtime: 'claude',
201
+ sessionId,
202
+ layer: 'bd',
203
+ kind: 'bd.auto_committed',
204
+ outcome: commit.ok ? 'allow' : 'block',
205
+ issueId: closedIssueId ?? null,
206
+ message: commit.message,
207
+ extra: { ok: commit.ok },
208
+ });
209
+ }
210
+
172
211
  const commitLine = commit
173
212
  ? `\n${commit.ok ? '✅' : '⚠️'} **Session Flow**: ${commit.message}`
174
213
  : '';
@@ -15,6 +15,7 @@ import {
15
15
  } from './beads-gate-core.mjs';
16
16
  import { withSafeBdContext } from './beads-gate-utils.mjs';
17
17
  import { commitBlockMessage } from './beads-gate-messages.mjs';
18
+ import { logEvent } from './xtrm-logger.mjs';
18
19
 
19
20
  const input = readHookInput();
20
21
  if (!input) process.exit(0);
@@ -35,10 +36,34 @@ withSafeBdContext(() => {
35
36
  const state = resolveClaimAndWorkState(ctx);
36
37
  const decision = decideCommitGate(ctx, state);
37
38
 
38
- if (decision.allow) process.exit(0);
39
+ if (decision.allow) {
40
+ logEvent({
41
+ cwd: ctx.cwd,
42
+ runtime: 'claude',
43
+ sessionId: ctx.sessionId,
44
+ layer: 'gate',
45
+ kind: 'hook.commit_gate.allow',
46
+ outcome: 'allow',
47
+ toolName: 'Bash',
48
+ issueId: state?.claimId ?? null,
49
+ });
50
+ process.exit(0);
51
+ }
39
52
 
40
53
  // Block with structured decision
41
54
  const reason = commitBlockMessage(decision.summary, decision.claimed);
55
+ logEvent({
56
+ cwd: ctx.cwd,
57
+ runtime: 'claude',
58
+ sessionId: ctx.sessionId,
59
+ layer: 'gate',
60
+ kind: 'hook.commit_gate.block',
61
+ outcome: 'block',
62
+ toolName: 'Bash',
63
+ issueId: decision.claimed ?? null,
64
+ message: reason,
65
+ extra: { reason_code: decision.reason },
66
+ });
42
67
  process.stdout.write(JSON.stringify({ decision: 'block', reason }));
43
68
  process.stdout.write('\n');
44
69
  process.exit(0);
@@ -14,8 +14,9 @@ import {
14
14
  decideEditGate,
15
15
  decideWorktreeBoundary,
16
16
  } from './beads-gate-core.mjs';
17
- import { withSafeBdContext, resolveCwd } from './beads-gate-utils.mjs';
17
+ import { withSafeBdContext, resolveCwd, resolveSessionId } from './beads-gate-utils.mjs';
18
18
  import { editBlockMessage, editBlockFallbackMessage } from './beads-gate-messages.mjs';
19
+ import { logEvent } from './xtrm-logger.mjs';
19
20
 
20
21
  const input = readHookInput();
21
22
  if (!input) process.exit(0);
@@ -24,10 +25,19 @@ if (!input) process.exit(0);
24
25
  const _cwd = resolveCwd(input);
25
26
  const _boundary = decideWorktreeBoundary(input, _cwd);
26
27
  if (!_boundary.allow) {
27
- process.stdout.write(JSON.stringify({
28
- decision: 'block',
29
- reason: `🚫 Edit outside worktree boundary.\n File: ${_boundary.filePath}\n Allowed: ${_boundary.worktreeRoot}\n\n All edits must stay within the active worktree.`,
30
- }));
28
+ const _wbReason = `🚫 Edit outside worktree boundary.\n File: ${_boundary.filePath}\n Allowed: ${_boundary.worktreeRoot}\n\n All edits must stay within the active worktree.`;
29
+ logEvent({
30
+ cwd: _cwd,
31
+ runtime: 'claude',
32
+ sessionId: resolveSessionId(input),
33
+ layer: 'gate',
34
+ kind: 'hook.worktree_boundary.block',
35
+ outcome: 'block',
36
+ toolName: input.tool_name,
37
+ message: _wbReason,
38
+ extra: { file: _boundary.filePath, worktree_root: _boundary.worktreeRoot },
39
+ });
40
+ process.stdout.write(JSON.stringify({ decision: 'block', reason: _wbReason }));
31
41
  process.stdout.write('\n');
32
42
  process.exit(0);
33
43
  }
@@ -39,12 +49,36 @@ withSafeBdContext(() => {
39
49
  const state = resolveClaimAndWorkState(ctx);
40
50
  const decision = decideEditGate(ctx, state);
41
51
 
42
- if (decision.allow) process.exit(0);
52
+ if (decision.allow) {
53
+ logEvent({
54
+ cwd: ctx.cwd,
55
+ runtime: 'claude',
56
+ sessionId: ctx.sessionId,
57
+ layer: 'gate',
58
+ kind: 'hook.edit_gate.allow',
59
+ outcome: 'allow',
60
+ toolName: input.tool_name,
61
+ issueId: state?.claimId ?? null,
62
+ extra: { file: input.tool_input?.file_path ?? null },
63
+ });
64
+ process.exit(0);
65
+ }
43
66
 
44
67
  // Block with appropriate message
45
68
  const reason = decision.reason === 'no_claim_with_work'
46
69
  ? editBlockMessage(decision.sessionId)
47
70
  : editBlockFallbackMessage();
71
+ logEvent({
72
+ cwd: ctx.cwd,
73
+ runtime: 'claude',
74
+ sessionId: ctx.sessionId,
75
+ layer: 'gate',
76
+ kind: 'hook.edit_gate.block',
77
+ outcome: 'block',
78
+ toolName: input.tool_name,
79
+ message: reason,
80
+ extra: { file: input.tool_input?.file_path ?? null, reason_code: decision.reason },
81
+ });
48
82
  process.stdout.write(JSON.stringify({ decision: 'block', reason }));
49
83
  process.stdout.write('\n');
50
84
  process.exit(0);
@@ -13,6 +13,7 @@ import { join } from 'node:path';
13
13
  import { readHookInput } from './beads-gate-core.mjs';
14
14
  import { resolveCwd, resolveSessionId, isBeadsProject, getSessionClaim, clearSessionClaim } from './beads-gate-utils.mjs';
15
15
  import { memoryPromptMessage } from './beads-gate-messages.mjs';
16
+ import { logEvent } from './xtrm-logger.mjs';
16
17
 
17
18
  const input = readHookInput();
18
19
  if (!input) process.exit(0);
@@ -35,6 +36,14 @@ if (existsSync(marker)) {
35
36
  timeout: 5000,
36
37
  });
37
38
  } catch { /* ignore */ }
39
+ logEvent({
40
+ cwd,
41
+ runtime: 'claude',
42
+ sessionId,
43
+ layer: 'gate',
44
+ kind: 'hook.memory_gate.acked',
45
+ outcome: 'allow',
46
+ });
38
47
  process.exit(0);
39
48
  }
40
49
 
@@ -57,5 +66,16 @@ try {
57
66
 
58
67
  if (!closedIssueId) process.exit(0);
59
68
 
60
- process.stderr.write(memoryPromptMessage());
69
+ const memoryMessage = memoryPromptMessage();
70
+ logEvent({
71
+ cwd,
72
+ runtime: 'claude',
73
+ sessionId,
74
+ layer: 'gate',
75
+ kind: 'hook.memory_gate.triggered',
76
+ outcome: 'block',
77
+ issueId: closedIssueId,
78
+ message: memoryMessage,
79
+ });
80
+ process.stderr.write(memoryMessage);
61
81
  process.exit(2);
@@ -12,6 +12,7 @@ import {
12
12
  } from './beads-gate-core.mjs';
13
13
  import { withSafeBdContext } from './beads-gate-utils.mjs';
14
14
  import { stopBlockMessage } from './beads-gate-messages.mjs';
15
+ import { logEvent } from './xtrm-logger.mjs';
15
16
 
16
17
  const input = readHookInput();
17
18
  if (!input) process.exit(0);
@@ -24,9 +25,29 @@ withSafeBdContext(() => {
24
25
  const decision = decideStopGate(ctx, state);
25
26
 
26
27
  if (!decision.allow) {
27
- process.stderr.write(stopBlockMessage(decision.summary, decision.claimed));
28
+ const message = stopBlockMessage(decision.summary, decision.claimed);
29
+ logEvent({
30
+ cwd: ctx.cwd,
31
+ runtime: 'claude',
32
+ sessionId: ctx.sessionId,
33
+ layer: 'gate',
34
+ kind: 'hook.stop_gate.block',
35
+ outcome: 'block',
36
+ issueId: decision.claimed ?? null,
37
+ message,
38
+ extra: { reason_code: decision.reason },
39
+ });
40
+ process.stderr.write(message);
28
41
  process.exit(2);
29
42
  }
30
43
 
44
+ logEvent({
45
+ cwd: ctx.cwd,
46
+ runtime: 'claude',
47
+ sessionId: ctx.sessionId,
48
+ layer: 'gate',
49
+ kind: 'hook.stop_gate.allow',
50
+ outcome: 'allow',
51
+ });
31
52
  process.exit(0);
32
53
  });
@@ -373,13 +373,13 @@ const config = loadConfig();
373
373
 
374
374
  // Logging functions - define before using
375
375
  const log = {
376
- info: (msg) => console.error(`${colors.blue}[INFO]${colors.reset} ${msg}`),
377
- error: (msg) => console.error(`${colors.red}[ERROR]${colors.reset} ${msg}`),
378
- success: (msg) => console.error(`${colors.green}[OK]${colors.reset} ${msg}`),
379
- warning: (msg) => console.error(`${colors.yellow}[WARN]${colors.reset} ${msg}`),
376
+ info: (msg) => console.log(`${colors.blue}[INFO]${colors.reset} ${msg}`),
377
+ error: (msg) => console.log(`${colors.red}[ERROR]${colors.reset} ${msg}`),
378
+ success: (msg) => console.log(`${colors.green}[OK]${colors.reset} ${msg}`),
379
+ warning: (msg) => console.log(`${colors.yellow}[WARN]${colors.reset} ${msg}`),
380
380
  debug: (msg) => {
381
381
  if (config.debug) {
382
- console.error(`${colors.cyan}[DEBUG]${colors.reset} ${msg}`);
382
+ console.log(`${colors.cyan}[DEBUG]${colors.reset} ${msg}`);
383
383
  }
384
384
  },
385
385
  };
@@ -622,7 +622,7 @@ class QualityChecker {
622
622
  const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
623
623
  diagnostic.start,
624
624
  );
625
- console.error(
625
+ console.log(
626
626
  ` ❌ ${diagnostic.file.fileName}:${line + 1}:${character + 1} - ${message}`,
627
627
  );
628
628
  });
@@ -634,16 +634,16 @@ class QualityChecker {
634
634
  diagnosticsByFile.forEach((diags, fileName) => {
635
635
  if (fileName !== this.filePath) {
636
636
  if (!hasDepErrors) {
637
- console.error('\n[DEPENDENCY ERRORS] Files imported by your edited file:');
637
+ console.log('\n[DEPENDENCY ERRORS] Files imported by your edited file:');
638
638
  hasDepErrors = true;
639
639
  }
640
- console.error(` ⚠️ ${fileName}:`);
640
+ console.log(` ⚠️ ${fileName}:`);
641
641
  diags.forEach((diagnostic) => {
642
642
  const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
643
643
  const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
644
644
  diagnostic.start,
645
645
  );
646
- console.error(` Line ${line + 1}:${character + 1} - ${message}`);
646
+ console.log(` Line ${line + 1}:${character + 1} - ${message}`);
647
647
  });
648
648
  }
649
649
  });
@@ -702,19 +702,19 @@ class QualityChecker {
702
702
  );
703
703
  const formatter = await eslint.loadFormatter('stylish');
704
704
  const output = formatter.format(resultsAfterFix);
705
- console.error(output);
705
+ console.log(output);
706
706
  }
707
707
  } else {
708
708
  this.errors.push(`ESLint found issues in ${this.filePath}`);
709
709
  const formatter = await eslint.loadFormatter('stylish');
710
710
  const output = formatter.format(results);
711
- console.error(output);
711
+ console.log(output);
712
712
  }
713
713
  } else {
714
714
  this.errors.push(`ESLint found issues in ${this.filePath}`);
715
715
  const formatter = await eslint.loadFormatter('stylish');
716
716
  const output = formatter.format(results);
717
- console.error(output);
717
+ console.log(output);
718
718
  }
719
719
  } else {
720
720
  log.success('ESLint passed');
@@ -763,7 +763,7 @@ class QualityChecker {
763
763
  }
764
764
  } else {
765
765
  this.errors.push(`Prettier formatting issues in ${this.filePath}`);
766
- console.error('Run prettier --write to fix');
766
+ console.log('Run prettier --write to fix');
767
767
  }
768
768
  } else {
769
769
  log.success('Prettier formatting correct');
@@ -799,7 +799,7 @@ class QualityChecker {
799
799
 
800
800
  if (severity === 'error') {
801
801
  this.errors.push(`Found 'as any' usage in ${this.filePath} - ${message}`);
802
- console.error(` Line ${index + 1}: ${line.trim()}`);
802
+ console.log(` Line ${index + 1}: ${line.trim()}`);
803
803
  foundIssues = true;
804
804
  } else {
805
805
  // Warning level - just warn, don't block
@@ -851,7 +851,7 @@ class QualityChecker {
851
851
 
852
852
  if (severity === 'error') {
853
853
  this.errors.push(`Found console statements in ${this.filePath} - ${message}`);
854
- console.error(` Line ${index + 1}: ${line.trim()}`);
854
+ console.log(` Line ${index + 1}: ${line.trim()}`);
855
855
  foundIssues = true;
856
856
  } else {
857
857
  // Info level - just warn, don't block
@@ -872,7 +872,7 @@ class QualityChecker {
872
872
 
873
873
  if (severity === 'error') {
874
874
  this.errors.push(`Found debugger statement in ${this.filePath} - ${message}`);
875
- console.error(` Line ${index + 1}: ${line.trim()}`);
875
+ console.log(` Line ${index + 1}: ${line.trim()}`);
876
876
  foundIssues = true;
877
877
  } else {
878
878
  log.warning(`Debugger statement at line ${index + 1}: ${message}`);
@@ -1050,7 +1050,7 @@ async function parseJsonInput() {
1050
1050
  log.info(
1051
1051
  'For testing, provide JSON like: echo \'{"tool_name":"Edit","tool_input":{"file_path":"/path/to/file.ts"}}\' | node hook.js',
1052
1052
  );
1053
- console.error(`\n${colors.yellow}👉 Hook executed but no input to process.${colors.reset}`);
1053
+ console.log(`\n${colors.yellow}👉 Hook executed but no input to process.${colors.reset}`);
1054
1054
  process.exit(0);
1055
1055
  }
1056
1056
 
@@ -1122,29 +1122,29 @@ function isSourceFile(filePath) {
1122
1122
  function printSummary(errors, autofixes) {
1123
1123
  // Show auto-fixes if any
1124
1124
  if (autofixes.length > 0) {
1125
- console.error(`\n${colors.blue}═══ Auto-fixes Applied ═══${colors.reset}`);
1125
+ console.log(`\n${colors.blue}═══ Auto-fixes Applied ═══${colors.reset}`);
1126
1126
  autofixes.forEach((fix) => {
1127
- console.error(`${colors.green}✨${colors.reset} ${fix}`);
1127
+ console.log(`${colors.green}✨${colors.reset} ${fix}`);
1128
1128
  });
1129
- console.error(
1129
+ console.log(
1130
1130
  `${colors.green}Automatically fixed ${autofixes.length} issue(s) for you!${colors.reset}`,
1131
1131
  );
1132
1132
  }
1133
1133
 
1134
1134
  // Show errors if any
1135
1135
  if (errors.length > 0) {
1136
- console.error(`\n${colors.blue}═══ Quality Check Summary ═══${colors.reset}`);
1136
+ console.log(`\n${colors.blue}═══ Quality Check Summary ═══${colors.reset}`);
1137
1137
  errors.forEach((error) => {
1138
- console.error(`${colors.red}❌${colors.reset} ${error}`);
1138
+ console.log(`${colors.red}❌${colors.reset} ${error}`);
1139
1139
  });
1140
1140
 
1141
- console.error(
1141
+ console.log(
1142
1142
  `\n${colors.red}Found ${errors.length} issue(s) that MUST be fixed!${colors.reset}`,
1143
1143
  );
1144
- console.error(`${colors.red}════════════════════════════════════════════${colors.reset}`);
1145
- console.error(`${colors.red}❌ ALL ISSUES ARE BLOCKING ❌${colors.reset}`);
1146
- console.error(`${colors.red}════════════════════════════════════════════${colors.reset}`);
1147
- console.error(`${colors.red}Fix EVERYTHING above until all checks are ✅ GREEN${colors.reset}`);
1144
+ console.log(`${colors.red}════════════════════════════════════════════${colors.reset}`);
1145
+ console.log(`${colors.red}❌ ALL ISSUES ARE BLOCKING ❌${colors.reset}`);
1146
+ console.log(`${colors.red}════════════════════════════════════════════${colors.reset}`);
1147
+ console.log(`${colors.red}Fix EVERYTHING above until all checks are ✅ GREEN${colors.reset}`);
1148
1148
  }
1149
1149
  }
1150
1150
 
@@ -1155,9 +1155,9 @@ function printSummary(errors, autofixes) {
1155
1155
  async function main() {
1156
1156
  // Show header with version
1157
1157
  const hookVersion = config._fileConfig.version || '1.0.0';
1158
- console.error('');
1159
- console.error(`📦 Node.js Quality Check v${hookVersion} - Starting...`);
1160
- console.error('────────────────────────────────────────────');
1158
+ console.log('');
1159
+ console.log(`📦 Node.js Quality Check v${hookVersion} - Starting...`);
1160
+ console.log('────────────────────────────────────────────');
1161
1161
 
1162
1162
  // Debug: show loaded configuration
1163
1163
  log.debug(`Loaded config: ${JSON.stringify(config, null, 2)}`);
@@ -1169,7 +1169,7 @@ async function main() {
1169
1169
  if (!filePath) {
1170
1170
  log.warning('No file path found in JSON input. Tool might not be file-related.');
1171
1171
  log.debug(`JSON input was: ${JSON.stringify(input)}`);
1172
- console.error(
1172
+ console.log(
1173
1173
  `\n${colors.yellow}👉 No file to check - tool may not be file-related.${colors.reset}`,
1174
1174
  );
1175
1175
  process.exit(0);
@@ -1178,24 +1178,24 @@ async function main() {
1178
1178
  // Check if file exists
1179
1179
  if (!(await fileExists(filePath))) {
1180
1180
  log.info(`File does not exist: ${filePath} (may have been deleted)`);
1181
- console.error(`\n${colors.yellow}👉 File skipped - doesn't exist.${colors.reset}`);
1181
+ console.log(`\n${colors.yellow}👉 File skipped - doesn't exist.${colors.reset}`);
1182
1182
  process.exit(0);
1183
1183
  }
1184
1184
 
1185
1185
  // For non-source files, exit successfully without checks (matching shell behavior)
1186
1186
  if (!isSourceFile(filePath)) {
1187
1187
  log.info(`Skipping non-source file: ${filePath}`);
1188
- console.error(`\n${colors.yellow}👉 File skipped - not a source file.${colors.reset}`);
1189
- console.error(
1188
+ console.log(`\n${colors.yellow}👉 File skipped - not a source file.${colors.reset}`);
1189
+ console.log(
1190
1190
  `\n${colors.green}✅ No checks needed for ${path.basename(filePath)}${colors.reset}`,
1191
1191
  );
1192
1192
  process.exit(0);
1193
1193
  }
1194
1194
 
1195
1195
  // Update header with file name
1196
- console.error('');
1197
- console.error(`🔍 Validating: ${path.basename(filePath)}`);
1198
- console.error('────────────────────────────────────────────');
1196
+ console.log('');
1197
+ console.log(`🔍 Validating: ${path.basename(filePath)}`);
1198
+ console.log('────────────────────────────────────────────');
1199
1199
  log.info(`Checking: ${filePath}`);
1200
1200
 
1201
1201
  // Run quality checks
@@ -1222,50 +1222,50 @@ async function main() {
1222
1222
  // Exit with appropriate code
1223
1223
  if (editedFileErrors.length > 0) {
1224
1224
  // Critical - blocks immediately
1225
- console.error(`\n${colors.red}🛑 FAILED - Fix issues in your edited file! 🛑${colors.reset}`);
1226
- console.error(`${colors.cyan}💡 CLAUDE.md CHECK:${colors.reset}`);
1227
- console.error(
1225
+ console.log(`\n${colors.red}🛑 FAILED - Fix issues in your edited file! 🛑${colors.reset}`);
1226
+ console.log(`${colors.cyan}💡 CLAUDE.md CHECK:${colors.reset}`);
1227
+ console.log(
1228
1228
  `${colors.cyan} → What CLAUDE.md pattern would have prevented this?${colors.reset}`,
1229
1229
  );
1230
- console.error(`${colors.cyan} → Are you following JSDoc batching strategy?${colors.reset}`);
1231
- console.error(`${colors.yellow}📋 NEXT STEPS:${colors.reset}`);
1232
- console.error(`${colors.yellow} 1. Fix the issues listed above${colors.reset}`);
1233
- console.error(`${colors.yellow} 2. The hook will run again automatically${colors.reset}`);
1234
- console.error(
1230
+ console.log(`${colors.cyan} → Are you following JSDoc batching strategy?${colors.reset}`);
1231
+ console.log(`${colors.yellow}📋 NEXT STEPS:${colors.reset}`);
1232
+ console.log(`${colors.yellow} 1. Fix the issues listed above${colors.reset}`);
1233
+ console.log(`${colors.yellow} 2. The hook will run again automatically${colors.reset}`);
1234
+ console.log(
1235
1235
  `${colors.yellow} 3. Continue with your original task once all checks pass${colors.reset}`,
1236
1236
  );
1237
1237
  process.exit(2);
1238
1238
  } else if (dependencyWarnings.length > 0) {
1239
1239
  // Warning - shows but doesn't block
1240
- console.error(`\n${colors.yellow}⚠️ WARNING - Dependency issues found${colors.reset}`);
1241
- console.error(
1240
+ console.log(`\n${colors.yellow}⚠️ WARNING - Dependency issues found${colors.reset}`);
1241
+ console.log(
1242
1242
  `${colors.yellow}These won't block your progress but should be addressed${colors.reset}`,
1243
1243
  );
1244
- console.error(
1244
+ console.log(
1245
1245
  `\n${colors.green}✅ Quality check passed for ${path.basename(filePath)}${colors.reset}`,
1246
1246
  );
1247
1247
 
1248
1248
  if (autofixes.length > 0 && config.autofixSilent) {
1249
- console.error(
1249
+ console.log(
1250
1250
  `\n${colors.yellow}👉 File quality verified. Auto-fixes applied. Continue with your task.${colors.reset}`,
1251
1251
  );
1252
1252
  } else {
1253
- console.error(
1253
+ console.log(
1254
1254
  `\n${colors.yellow}👉 File quality verified. Continue with your task.${colors.reset}`,
1255
1255
  );
1256
1256
  }
1257
1257
  process.exit(0); // Don't block on dependency issues
1258
1258
  } else {
1259
- console.error(
1259
+ console.log(
1260
1260
  `\n${colors.green}✅ Quality check passed for ${path.basename(filePath)}${colors.reset}`,
1261
1261
  );
1262
1262
 
1263
1263
  if (autofixes.length > 0 && config.autofixSilent) {
1264
- console.error(
1264
+ console.log(
1265
1265
  `\n${colors.yellow}👉 File quality verified. Auto-fixes applied. Continue with your task.${colors.reset}`,
1266
1266
  );
1267
1267
  } else {
1268
- console.error(
1268
+ console.log(
1269
1269
  `\n${colors.yellow}👉 File quality verified. Continue with your task.${colors.reset}`,
1270
1270
  );
1271
1271
  }