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/dist/index.cjs +202 -9
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/hooks/beads-claim-sync.mjs +39 -0
- package/hooks/beads-commit-gate.mjs +26 -1
- package/hooks/beads-edit-gate.mjs +40 -6
- package/hooks/beads-memory-gate.mjs +21 -1
- package/hooks/beads-stop-gate.mjs +22 -1
- package/hooks/quality-check.cjs +53 -53
- package/hooks/quality-check.py +36 -36
- package/hooks/xtrm-logger.mjs +123 -0
- package/package.json +1 -1
package/cli/package.json
CHANGED
|
@@ -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)
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|
package/hooks/quality-check.cjs
CHANGED
|
@@ -373,13 +373,13 @@ const config = loadConfig();
|
|
|
373
373
|
|
|
374
374
|
// Logging functions - define before using
|
|
375
375
|
const log = {
|
|
376
|
-
info: (msg) => console.
|
|
377
|
-
error: (msg) => console.
|
|
378
|
-
success: (msg) => console.
|
|
379
|
-
warning: (msg) => console.
|
|
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.
|
|
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.
|
|
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.
|
|
637
|
+
console.log('\n[DEPENDENCY ERRORS] Files imported by your edited file:');
|
|
638
638
|
hasDepErrors = true;
|
|
639
639
|
}
|
|
640
|
-
console.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
1125
|
+
console.log(`\n${colors.blue}═══ Auto-fixes Applied ═══${colors.reset}`);
|
|
1126
1126
|
autofixes.forEach((fix) => {
|
|
1127
|
-
console.
|
|
1127
|
+
console.log(`${colors.green}✨${colors.reset} ${fix}`);
|
|
1128
1128
|
});
|
|
1129
|
-
console.
|
|
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.
|
|
1136
|
+
console.log(`\n${colors.blue}═══ Quality Check Summary ═══${colors.reset}`);
|
|
1137
1137
|
errors.forEach((error) => {
|
|
1138
|
-
console.
|
|
1138
|
+
console.log(`${colors.red}❌${colors.reset} ${error}`);
|
|
1139
1139
|
});
|
|
1140
1140
|
|
|
1141
|
-
console.
|
|
1141
|
+
console.log(
|
|
1142
1142
|
`\n${colors.red}Found ${errors.length} issue(s) that MUST be fixed!${colors.reset}`,
|
|
1143
1143
|
);
|
|
1144
|
-
console.
|
|
1145
|
-
console.
|
|
1146
|
-
console.
|
|
1147
|
-
console.
|
|
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.
|
|
1159
|
-
console.
|
|
1160
|
-
console.
|
|
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.
|
|
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.
|
|
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.
|
|
1189
|
-
console.
|
|
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.
|
|
1197
|
-
console.
|
|
1198
|
-
console.
|
|
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.
|
|
1226
|
-
console.
|
|
1227
|
-
console.
|
|
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.
|
|
1231
|
-
console.
|
|
1232
|
-
console.
|
|
1233
|
-
console.
|
|
1234
|
-
console.
|
|
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.
|
|
1241
|
-
console.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
1268
|
+
console.log(
|
|
1269
1269
|
`\n${colors.yellow}👉 File quality verified. Continue with your task.${colors.reset}`,
|
|
1270
1270
|
);
|
|
1271
1271
|
}
|