Skip to content

Commit bfbd416

Browse files
committed
fix: nx full-hog
1 parent 5f7184a commit bfbd416

43 files changed

Lines changed: 1319 additions & 3065 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/hooks/scripts/session-start.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ try {
2121
}
2222

2323
const output = {
24-
systemMessage: [
25-
'The following is CONTRIBUTING.md for this repository.',
26-
'Read and internalize it before proceeding — pay particular attention to',
27-
'the three error phases and where validations belong.',
28-
'',
29-
contributing,
30-
].join('\n'),
24+
hookSpecificOutput: {
25+
hookEventName: 'SessionStart',
26+
additionalContext: [
27+
'The following is CONTRIBUTING.md for this repository.',
28+
'Read and internalize it before proceeding — pay particular attention to',
29+
'the three error phases and where validations belong.',
30+
'',
31+
contributing,
32+
].join('\n'),
33+
},
3134
};
3235

3336
process.stdout.write(JSON.stringify(output));
Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,56 @@
11
#!/usr/bin/env node
22

33
/**
4-
* Stop hook: runs `dotnet build` before the agent yields back to the user and
5-
* injects the result as a system message. Build errors surface immediately so
6-
* the agent can address them before the next prompt rather than discovering
7-
* them later.
4+
* Stop hook: runs `dotnet build` and reports only warnings/errors.
5+
* - No C# changes in working tree: skips the build entirely.
6+
* - Clean build: brief success message via systemMessage.
7+
* - Warnings present: systemMessage with filtered warning lines.
8+
* - Build failure / errors: blocks the agent via hookSpecificOutput so it can
9+
* address errors before concluding.
10+
*
11+
* Reads stdin to check stop_hook_active and avoid infinite loops.
812
*/
913

1014
const { spawnSync } = require('child_process');
1115
const path = require('path');
1216

17+
// Read and parse stdin to detect re-entry.
18+
let hookInput = {};
19+
try {
20+
const raw = require('fs').readFileSync('/dev/stdin', 'utf-8').trim();
21+
if (raw) hookInput = JSON.parse(raw);
22+
} catch (_) {
23+
// stdin unavailable or empty — treat as first invocation.
24+
}
25+
26+
// Prevent infinite loop: if we are already in a stop-hook continuation, exit cleanly.
27+
if (hookInput.stop_hook_active) {
28+
process.exit(0);
29+
}
30+
1331
const repoRoot = path.resolve(__dirname, '../../..');
1432

33+
// Short-circuit if no C#-related files are dirty (staged or unstaged vs HEAD).
34+
const CSHARP_PATTERN = /\.(cs|csproj|fsproj|slnx|sln|props|targets)$|^(global\.json|NuGet\.Config)$/i;
35+
36+
const gitStatus = spawnSync('git', ['status', '--porcelain'], {
37+
cwd: repoRoot,
38+
encoding: 'utf-8',
39+
});
40+
const dirtyFiles = (gitStatus.stdout || '').trim().split('\n').filter(Boolean);
41+
const hasCSharpChanges = dirtyFiles.some(line => {
42+
// Each line is "XY filename" or "XY old -> new"; grab the last path segment.
43+
const filePath = line.slice(3).trim().split(' -> ').pop();
44+
return CSHARP_PATTERN.test(path.basename(filePath));
45+
});
46+
47+
if (!hasCSharpChanges) {
48+
process.stdout.write(JSON.stringify({
49+
systemMessage: 'dotnet build: skipped (no C# changes detected in working tree).',
50+
}));
51+
process.exit(0);
52+
}
53+
1554
const result = spawnSync('dotnet', ['build', 'Flowthru.slnx'], {
1655
cwd: repoRoot,
1756
encoding: 'utf-8',
@@ -22,21 +61,40 @@ const stdout = (result.stdout || '').trim();
2261
const stderr = (result.stderr || '').trim();
2362
const combined = [stdout, stderr].filter(Boolean).join('\n');
2463

25-
const succeeded = result.status === 0;
26-
const headline = succeeded
27-
? 'dotnet build succeeded.'
28-
: 'dotnet build FAILED — address these errors before concluding.';
29-
30-
const output = {
31-
systemMessage: [
32-
`## Build Check (dotnet build)`,
33-
'',
34-
headline,
35-
'',
36-
'```',
37-
combined,
38-
'```',
39-
].join('\n'),
40-
};
41-
42-
process.stdout.write(JSON.stringify(output));
64+
// Extract compiler diagnostics: lines containing ': warning XXXX' or ': error XXXX'.
65+
const diagnosticLines = combined
66+
.split('\n')
67+
.filter(line => /:\s*(warning|error)\s+[A-Za-z]*\d+/i.test(line));
68+
69+
const hasErrors = result.status !== 0 || diagnosticLines.some(l => /:\s*error\s+/i.test(l));
70+
const hasWarnings = diagnosticLines.some(l => /:\s*warning\s+/i.test(l));
71+
72+
if (hasErrors) {
73+
// Block the agent so it addresses errors before concluding.
74+
const diagnosticSummary = diagnosticLines.length > 0
75+
? diagnosticLines.join('\n')
76+
: combined; // fall back to full output if pattern didn't match anything
77+
process.stdout.write(JSON.stringify({
78+
hookSpecificOutput: {
79+
hookEventName: 'Stop',
80+
decision: 'block',
81+
reason: [
82+
'dotnet build FAILED — address these errors before concluding.',
83+
'',
84+
diagnosticSummary,
85+
].join('\n'),
86+
},
87+
}));
88+
} else if (hasWarnings) {
89+
process.stdout.write(JSON.stringify({
90+
systemMessage: [
91+
'dotnet build succeeded with warnings:',
92+
'',
93+
diagnosticLines.join('\n'),
94+
].join('\n'),
95+
}));
96+
} else {
97+
process.stdout.write(JSON.stringify({
98+
systemMessage: 'dotnet build: succeeded with no warnings or errors.',
99+
}));
100+
}

0 commit comments

Comments
 (0)