@mohantn/gate-keeper 2.1.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.
- package/.github/instructions/dotnet-api-integration.instructions.md +416 -0
- package/.github/instructions/dotnet-development.instructions.md +353 -0
- package/.github/instructions/dotnet-testing.instructions.md +406 -0
- package/.github/instructions/gate-keeper.instructions.md +91 -0
- package/.github/instructions/react-development.instructions.md +315 -0
- package/.github/instructions/react-testing-optimization.instructions.md +373 -0
- package/.github/instructions/uiux.instructions.md +261 -0
- package/LICENSE +21 -0
- package/README.md +181 -0
- package/dist/analyzer/coverage-analyzer.d.ts +126 -0
- package/dist/analyzer/coverage-analyzer.d.ts.map +1 -0
- package/dist/analyzer/coverage-analyzer.js +633 -0
- package/dist/analyzer/coverage-analyzer.js.map +1 -0
- package/dist/analyzer/csharp-analyzer.d.ts +28 -0
- package/dist/analyzer/csharp-analyzer.d.ts.map +1 -0
- package/dist/analyzer/csharp-analyzer.js +437 -0
- package/dist/analyzer/csharp-analyzer.js.map +1 -0
- package/dist/analyzer/pattern-detector.d.ts +5 -0
- package/dist/analyzer/pattern-detector.d.ts.map +1 -0
- package/dist/analyzer/pattern-detector.js +74 -0
- package/dist/analyzer/pattern-detector.js.map +1 -0
- package/dist/analyzer/refactoring-advisor.d.ts +7 -0
- package/dist/analyzer/refactoring-advisor.d.ts.map +1 -0
- package/dist/analyzer/refactoring-advisor.js +280 -0
- package/dist/analyzer/refactoring-advisor.js.map +1 -0
- package/dist/analyzer/sonar-eslint-runner.d.ts +3 -0
- package/dist/analyzer/sonar-eslint-runner.d.ts.map +1 -0
- package/dist/analyzer/sonar-eslint-runner.js +136 -0
- package/dist/analyzer/sonar-eslint-runner.js.map +1 -0
- package/dist/analyzer/sonar-rule-map.d.ts +19 -0
- package/dist/analyzer/sonar-rule-map.d.ts.map +1 -0
- package/dist/analyzer/sonar-rule-map.js +67 -0
- package/dist/analyzer/sonar-rule-map.js.map +1 -0
- package/dist/analyzer/string-analyzer.d.ts +27 -0
- package/dist/analyzer/string-analyzer.d.ts.map +1 -0
- package/dist/analyzer/string-analyzer.js +274 -0
- package/dist/analyzer/string-analyzer.js.map +1 -0
- package/dist/analyzer/typescript-analyzer.d.ts +27 -0
- package/dist/analyzer/typescript-analyzer.d.ts.map +1 -0
- package/dist/analyzer/typescript-analyzer.js +437 -0
- package/dist/analyzer/typescript-analyzer.js.map +1 -0
- package/dist/analyzer/universal-analyzer.d.ts +10 -0
- package/dist/analyzer/universal-analyzer.d.ts.map +1 -0
- package/dist/analyzer/universal-analyzer.js +155 -0
- package/dist/analyzer/universal-analyzer.js.map +1 -0
- package/dist/cache/quality-cache.d.ts +119 -0
- package/dist/cache/quality-cache.d.ts.map +1 -0
- package/dist/cache/quality-cache.js +130 -0
- package/dist/cache/quality-cache.js.map +1 -0
- package/dist/cache/sqlite-cache.d.ts +43 -0
- package/dist/cache/sqlite-cache.d.ts.map +1 -0
- package/dist/cache/sqlite-cache.js +346 -0
- package/dist/cache/sqlite-cache.js.map +1 -0
- package/dist/cli/query-repl.d.ts +37 -0
- package/dist/cli/query-repl.d.ts.map +1 -0
- package/dist/cli/query-repl.js +298 -0
- package/dist/cli/query-repl.js.map +1 -0
- package/dist/cli/repl-algorithms.d.ts +49 -0
- package/dist/cli/repl-algorithms.d.ts.map +1 -0
- package/dist/cli/repl-algorithms.js +147 -0
- package/dist/cli/repl-algorithms.js.map +1 -0
- package/dist/cli/setup-core.d.ts +38 -0
- package/dist/cli/setup-core.d.ts.map +1 -0
- package/dist/cli/setup-core.js +427 -0
- package/dist/cli/setup-core.js.map +1 -0
- package/dist/cli/setup.d.ts +25 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +159 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli-entry.d.ts +19 -0
- package/dist/cli-entry.d.ts.map +1 -0
- package/dist/cli-entry.js +178 -0
- package/dist/cli-entry.js.map +1 -0
- package/dist/daemon/watch-mode.d.ts +41 -0
- package/dist/daemon/watch-mode.d.ts.map +1 -0
- package/dist/daemon/watch-mode.js +163 -0
- package/dist/daemon/watch-mode.js.map +1 -0
- package/dist/daemon.d.ts +24 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +357 -0
- package/dist/daemon.js.map +1 -0
- package/dist/github/app.d.ts +34 -0
- package/dist/github/app.d.ts.map +1 -0
- package/dist/github/app.js +261 -0
- package/dist/github/app.js.map +1 -0
- package/dist/github/commenter.d.ts +67 -0
- package/dist/github/commenter.d.ts.map +1 -0
- package/dist/github/commenter.js +155 -0
- package/dist/github/commenter.js.map +1 -0
- package/dist/graph/dependency-graph.d.ts +28 -0
- package/dist/graph/dependency-graph.d.ts.map +1 -0
- package/dist/graph/dependency-graph.js +198 -0
- package/dist/graph/dependency-graph.js.map +1 -0
- package/dist/graph/global-graph.d.ts +65 -0
- package/dist/graph/global-graph.d.ts.map +1 -0
- package/dist/graph/global-graph.js +153 -0
- package/dist/graph/global-graph.js.map +1 -0
- package/dist/graph/graph-algorithms.d.ts +90 -0
- package/dist/graph/graph-algorithms.d.ts.map +1 -0
- package/dist/graph/graph-algorithms.js +180 -0
- package/dist/graph/graph-algorithms.js.map +1 -0
- package/dist/graph/graph-export.d.ts +68 -0
- package/dist/graph/graph-export.d.ts.map +1 -0
- package/dist/graph/graph-export.js +264 -0
- package/dist/graph/graph-export.js.map +1 -0
- package/dist/graph/graph-report.d.ts +34 -0
- package/dist/graph/graph-report.d.ts.map +1 -0
- package/dist/graph/graph-report.js +136 -0
- package/dist/graph/graph-report.js.map +1 -0
- package/dist/graph/graph-summary.d.ts +68 -0
- package/dist/graph/graph-summary.d.ts.map +1 -0
- package/dist/graph/graph-summary.js +213 -0
- package/dist/graph/graph-summary.js.map +1 -0
- package/dist/graph/graphify-ignore.d.ts +32 -0
- package/dist/graph/graphify-ignore.d.ts.map +1 -0
- package/dist/graph/graphify-ignore.js +124 -0
- package/dist/graph/graphify-ignore.js.map +1 -0
- package/dist/graph/question-suggester.d.ts +30 -0
- package/dist/graph/question-suggester.d.ts.map +1 -0
- package/dist/graph/question-suggester.js +113 -0
- package/dist/graph/question-suggester.js.map +1 -0
- package/dist/graph/relationship-extractor.d.ts +40 -0
- package/dist/graph/relationship-extractor.d.ts.map +1 -0
- package/dist/graph/relationship-extractor.js +254 -0
- package/dist/graph/relationship-extractor.js.map +1 -0
- package/dist/graph/relationship-types.d.ts +24 -0
- package/dist/graph/relationship-types.d.ts.map +1 -0
- package/dist/graph/relationship-types.js +21 -0
- package/dist/graph/relationship-types.js.map +1 -0
- package/dist/graph/surprising-connections.d.ts +39 -0
- package/dist/graph/surprising-connections.d.ts.map +1 -0
- package/dist/graph/surprising-connections.js +127 -0
- package/dist/graph/surprising-connections.js.map +1 -0
- package/dist/hook-pre-tool-use.d.ts +14 -0
- package/dist/hook-pre-tool-use.d.ts.map +1 -0
- package/dist/hook-pre-tool-use.js +167 -0
- package/dist/hook-pre-tool-use.js.map +1 -0
- package/dist/hook-receiver.d.ts +29 -0
- package/dist/hook-receiver.d.ts.map +1 -0
- package/dist/hook-receiver.js +327 -0
- package/dist/hook-receiver.js.map +1 -0
- package/dist/hooks/git-hooks.d.ts +30 -0
- package/dist/hooks/git-hooks.d.ts.map +1 -0
- package/dist/hooks/git-hooks.js +179 -0
- package/dist/hooks/git-hooks.js.map +1 -0
- package/dist/mcp/cache-preload.d.ts +29 -0
- package/dist/mcp/cache-preload.d.ts.map +1 -0
- package/dist/mcp/cache-preload.js +103 -0
- package/dist/mcp/cache-preload.js.map +1 -0
- package/dist/mcp/handlers/analysis.d.ts +4 -0
- package/dist/mcp/handlers/analysis.d.ts.map +1 -0
- package/dist/mcp/handlers/analysis.js +196 -0
- package/dist/mcp/handlers/analysis.js.map +1 -0
- package/dist/mcp/handlers/context.d.ts +25 -0
- package/dist/mcp/handlers/context.d.ts.map +1 -0
- package/dist/mcp/handlers/context.js +382 -0
- package/dist/mcp/handlers/context.js.map +1 -0
- package/dist/mcp/handlers/graph-intelligence.d.ts +26 -0
- package/dist/mcp/handlers/graph-intelligence.d.ts.map +1 -0
- package/dist/mcp/handlers/graph-intelligence.js +371 -0
- package/dist/mcp/handlers/graph-intelligence.js.map +1 -0
- package/dist/mcp/handlers/graph-query.d.ts +25 -0
- package/dist/mcp/handlers/graph-query.d.ts.map +1 -0
- package/dist/mcp/handlers/graph-query.js +410 -0
- package/dist/mcp/handlers/graph-query.js.map +1 -0
- package/dist/mcp/handlers/graph.d.ts +5 -0
- package/dist/mcp/handlers/graph.d.ts.map +1 -0
- package/dist/mcp/handlers/graph.js +283 -0
- package/dist/mcp/handlers/graph.js.map +1 -0
- package/dist/mcp/handlers/impact-format.d.ts +9 -0
- package/dist/mcp/handlers/impact-format.d.ts.map +1 -0
- package/dist/mcp/handlers/impact-format.js +189 -0
- package/dist/mcp/handlers/impact-format.js.map +1 -0
- package/dist/mcp/handlers/impact.d.ts +4 -0
- package/dist/mcp/handlers/impact.d.ts.map +1 -0
- package/dist/mcp/handlers/impact.js +139 -0
- package/dist/mcp/handlers/impact.js.map +1 -0
- package/dist/mcp/handlers/improvement.d.ts +4 -0
- package/dist/mcp/handlers/improvement.d.ts.map +1 -0
- package/dist/mcp/handlers/improvement.js +136 -0
- package/dist/mcp/handlers/improvement.js.map +1 -0
- package/dist/mcp/handlers/index.d.ts +14 -0
- package/dist/mcp/handlers/index.d.ts.map +1 -0
- package/dist/mcp/handlers/index.js +36 -0
- package/dist/mcp/handlers/index.js.map +1 -0
- package/dist/mcp/handlers/platform-installer.d.ts +10 -0
- package/dist/mcp/handlers/platform-installer.d.ts.map +1 -0
- package/dist/mcp/handlers/platform-installer.js +168 -0
- package/dist/mcp/handlers/platform-installer.js.map +1 -0
- package/dist/mcp/handlers/pr-review.d.ts +33 -0
- package/dist/mcp/handlers/pr-review.d.ts.map +1 -0
- package/dist/mcp/handlers/pr-review.js +170 -0
- package/dist/mcp/handlers/pr-review.js.map +1 -0
- package/dist/mcp/handlers/shared.d.ts +20 -0
- package/dist/mcp/handlers/shared.d.ts.map +1 -0
- package/dist/mcp/handlers/shared.js +27 -0
- package/dist/mcp/handlers/shared.js.map +1 -0
- package/dist/mcp/handlers/types.d.ts +46 -0
- package/dist/mcp/handlers/types.d.ts.map +1 -0
- package/dist/mcp/handlers/types.js +3 -0
- package/dist/mcp/handlers/types.js.map +1 -0
- package/dist/mcp/helpers.d.ts +36 -0
- package/dist/mcp/helpers.d.ts.map +1 -0
- package/dist/mcp/helpers.js +199 -0
- package/dist/mcp/helpers.js.map +1 -0
- package/dist/mcp/installer.d.ts +22 -0
- package/dist/mcp/installer.d.ts.map +1 -0
- package/dist/mcp/installer.js +341 -0
- package/dist/mcp/installer.js.map +1 -0
- package/dist/mcp/server.d.ts +111 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +216 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/token-tracker.d.ts +47 -0
- package/dist/mcp/token-tracker.d.ts.map +1 -0
- package/dist/mcp/token-tracker.js +93 -0
- package/dist/mcp/token-tracker.js.map +1 -0
- package/dist/quality-loop/file-lock.d.ts +12 -0
- package/dist/quality-loop/file-lock.d.ts.map +1 -0
- package/dist/quality-loop/file-lock.js +38 -0
- package/dist/quality-loop/file-lock.js.map +1 -0
- package/dist/quality-loop/fix-worker.d.ts +44 -0
- package/dist/quality-loop/fix-worker.d.ts.map +1 -0
- package/dist/quality-loop/fix-worker.js +414 -0
- package/dist/quality-loop/fix-worker.js.map +1 -0
- package/dist/quality-loop/orchestrator.d.ts +137 -0
- package/dist/quality-loop/orchestrator.d.ts.map +1 -0
- package/dist/quality-loop/orchestrator.js +894 -0
- package/dist/quality-loop/orchestrator.js.map +1 -0
- package/dist/quality-loop/queue-manager.d.ts +45 -0
- package/dist/quality-loop/queue-manager.d.ts.map +1 -0
- package/dist/quality-loop/queue-manager.js +173 -0
- package/dist/quality-loop/queue-manager.js.map +1 -0
- package/dist/rating/rating-calculator.d.ts +15 -0
- package/dist/rating/rating-calculator.d.ts.map +1 -0
- package/dist/rating/rating-calculator.js +136 -0
- package/dist/rating/rating-calculator.js.map +1 -0
- package/dist/types/agent.d.ts +49 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +7 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types.d.ts +156 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/util/fix-text.d.ts +7 -0
- package/dist/util/fix-text.d.ts.map +1 -0
- package/dist/util/fix-text.js +13 -0
- package/dist/util/fix-text.js.map +1 -0
- package/dist/viz/graph-viz.d.ts +40 -0
- package/dist/viz/graph-viz.d.ts.map +1 -0
- package/dist/viz/graph-viz.js +332 -0
- package/dist/viz/graph-viz.js.map +1 -0
- package/dist/viz/viz-helpers.d.ts +13 -0
- package/dist/viz/viz-helpers.d.ts.map +1 -0
- package/dist/viz/viz-helpers.js +134 -0
- package/dist/viz/viz-helpers.js.map +1 -0
- package/dist/viz/viz-routes.d.ts +28 -0
- package/dist/viz/viz-routes.d.ts.map +1 -0
- package/dist/viz/viz-routes.js +333 -0
- package/dist/viz/viz-routes.js.map +1 -0
- package/dist/viz/viz-scanner.d.ts +20 -0
- package/dist/viz/viz-scanner.d.ts.map +1 -0
- package/dist/viz/viz-scanner.js +241 -0
- package/dist/viz/viz-scanner.js.map +1 -0
- package/dist/viz/viz-server.d.ts +38 -0
- package/dist/viz/viz-server.d.ts.map +1 -0
- package/dist/viz/viz-server.js +240 -0
- package/dist/viz/viz-server.js.map +1 -0
- package/package.json +89 -0
- package/scripts/postinstall.js +28 -0
- package/scripts/setup.sh +113 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* gate-keeper pre-tool-use hook
|
|
4
|
+
*
|
|
5
|
+
* Called by Claude Code's PreToolUse hook on every Write/Edit operation.
|
|
6
|
+
* Calls the daemon's check_pre_edit_safety endpoint and prints a warning
|
|
7
|
+
* (exit code 0 — non-blocking) if the edit would impact 3+ fragile
|
|
8
|
+
* dependents or has a "block" verdict.
|
|
9
|
+
*
|
|
10
|
+
* The warning is printed to stderr so Claude sees it but the edit is
|
|
11
|
+
* allowed to proceed. This is a safety advisory, not a gate — for
|
|
12
|
+
* blocking quality gates, see hook-receiver.ts (PostToolUse).
|
|
13
|
+
*/
|
|
14
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
17
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
19
|
+
}
|
|
20
|
+
Object.defineProperty(o, k2, desc);
|
|
21
|
+
}) : (function(o, m, k, k2) {
|
|
22
|
+
if (k2 === undefined) k2 = k;
|
|
23
|
+
o[k2] = m[k];
|
|
24
|
+
}));
|
|
25
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
26
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
27
|
+
}) : function(o, v) {
|
|
28
|
+
o["default"] = v;
|
|
29
|
+
});
|
|
30
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
31
|
+
var ownKeys = function(o) {
|
|
32
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
33
|
+
var ar = [];
|
|
34
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
35
|
+
return ar;
|
|
36
|
+
};
|
|
37
|
+
return ownKeys(o);
|
|
38
|
+
};
|
|
39
|
+
return function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
})();
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.main = main;
|
|
49
|
+
const http = __importStar(require("http"));
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const child_process_1 = require("child_process");
|
|
53
|
+
const DAEMON_PORT = 5378;
|
|
54
|
+
const GK_DIR = path.join(process.env.HOME ?? '/tmp', '.gate-keeper');
|
|
55
|
+
const PID_FILE = path.join(GK_DIR, 'daemon.pid');
|
|
56
|
+
const WATCHED_EXTENSIONS = new Set(['.ts', '.tsx', '.jsx', '.js', '.cs']);
|
|
57
|
+
// ── Daemon liveness check ─────────────────────────────────
|
|
58
|
+
function isDaemonAlive() {
|
|
59
|
+
try {
|
|
60
|
+
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf8').trim(), 10);
|
|
61
|
+
if (isNaN(pid))
|
|
62
|
+
return false;
|
|
63
|
+
process.kill(pid, 0);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ── Daemon API call ───────────────────────────────────────
|
|
71
|
+
function fetchDaemonApi(urlPath, body) {
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
const isPost = !!body;
|
|
74
|
+
const req = http.request(`http://127.0.0.1:${DAEMON_PORT}${urlPath}`, {
|
|
75
|
+
method: isPost ? 'POST' : 'GET',
|
|
76
|
+
timeout: 5000,
|
|
77
|
+
headers: isPost ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } : {},
|
|
78
|
+
}, (res) => {
|
|
79
|
+
let data = '';
|
|
80
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
81
|
+
res.on('end', () => {
|
|
82
|
+
try {
|
|
83
|
+
resolve(JSON.parse(data));
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
resolve(null);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
req.on('error', () => resolve(null));
|
|
91
|
+
req.on('timeout', () => { req.destroy(); resolve(null); });
|
|
92
|
+
if (body)
|
|
93
|
+
req.write(body);
|
|
94
|
+
req.end();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// ── Git repo root ─────────────────────────────────────────
|
|
98
|
+
function findGitRoot(dir) {
|
|
99
|
+
const result = (0, child_process_1.spawnSync)('git', ['rev-parse', '--show-toplevel'], {
|
|
100
|
+
cwd: dir, encoding: 'utf8', timeout: 3000,
|
|
101
|
+
});
|
|
102
|
+
return result.status === 0 && result.stdout.trim() ? result.stdout.trim() : dir;
|
|
103
|
+
}
|
|
104
|
+
// ── Main ──────────────────────────────────────────────────
|
|
105
|
+
async function main() {
|
|
106
|
+
// Read the JSON payload from stdin (Claude Code passes the hook event as JSON)
|
|
107
|
+
let payload = '';
|
|
108
|
+
process.stdin.setEncoding('utf8');
|
|
109
|
+
for await (const chunk of process.stdin)
|
|
110
|
+
payload += chunk;
|
|
111
|
+
let event;
|
|
112
|
+
try {
|
|
113
|
+
event = JSON.parse(payload);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return; // Not valid JSON — silently pass through
|
|
117
|
+
}
|
|
118
|
+
// Extract the file path from the tool input
|
|
119
|
+
const toolInput = event['tool_input'];
|
|
120
|
+
if (!toolInput)
|
|
121
|
+
return;
|
|
122
|
+
const filePath = (toolInput['file_path'] ?? toolInput['path'] ?? '');
|
|
123
|
+
if (!filePath)
|
|
124
|
+
return;
|
|
125
|
+
const ext = path.extname(filePath);
|
|
126
|
+
if (!WATCHED_EXTENSIONS.has(ext))
|
|
127
|
+
return;
|
|
128
|
+
if (!isDaemonAlive())
|
|
129
|
+
return;
|
|
130
|
+
// Resolve the repo root
|
|
131
|
+
const cwd = (event['cwd'] ?? process.cwd());
|
|
132
|
+
const repo = findGitRoot(cwd);
|
|
133
|
+
const encodedRepo = encodeURIComponent(repo);
|
|
134
|
+
// Call the dedicated impact-set API endpoint
|
|
135
|
+
const encodedFile = encodeURIComponent(filePath);
|
|
136
|
+
const impactResult = await fetchDaemonApi(`/api/impact-set?file=${encodedFile}&repo=${encodedRepo}&depth=1`);
|
|
137
|
+
if (!impactResult)
|
|
138
|
+
return;
|
|
139
|
+
// Warning conditions — fragile dependent check
|
|
140
|
+
if (impactResult.verdict === 'block' || (impactResult.fragileCount ?? 0) >= 3) {
|
|
141
|
+
const lines = [
|
|
142
|
+
`[Gate Keeper] ⚠️ Pre-edit safety warning: ${path.basename(filePath)}`,
|
|
143
|
+
` ${impactResult.reason ?? 'File has fragile dependents'} — proceeding with edit`,
|
|
144
|
+
` Rating: ${impactResult.fileRating ?? '?'}/10 · Direct dependents: ${impactResult.directDependents ?? 0} · Fragile: ${impactResult.fragileCount ?? 0}`,
|
|
145
|
+
];
|
|
146
|
+
// List fragile/affected dependents if available
|
|
147
|
+
const fragileFiles = (impactResult.affected ?? [])
|
|
148
|
+
.filter(f => f.fragile)
|
|
149
|
+
.slice(0, 10);
|
|
150
|
+
if (fragileFiles.length > 0) {
|
|
151
|
+
lines.push(` Dependent files at risk:`);
|
|
152
|
+
for (const f of fragileFiles) {
|
|
153
|
+
lines.push(` - ${f.path} (rating ${f.rating}/10)`);
|
|
154
|
+
}
|
|
155
|
+
if ((impactResult.fragileCount ?? 0) > fragileFiles.length) {
|
|
156
|
+
lines.push(` ... and ${(impactResult.fragileCount ?? 0) - fragileFiles.length} more`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
lines.push(` Proceed with extra care — update all references and run tests after editing.`, ` Use get_impact_set(file_path="${filePath}", depth=1) for the full impact set.`);
|
|
160
|
+
process.stderr.write(lines.join('\n') + '\n');
|
|
161
|
+
// Exit 0 — warn but allow the edit to proceed
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (require.main === module) {
|
|
165
|
+
main().catch(() => process.exit(0)); // Errors are non-blocking — pass through
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=hook-pre-tool-use.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-pre-tool-use.js","sourceRoot":"","sources":["../src/hook-pre-tool-use.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gate-keeper hook-receiver
|
|
3
|
+
*
|
|
4
|
+
* Called by Claude Code's PostToolUse hook on every Write/Edit operation,
|
|
5
|
+
* and also on session_create events to register new repos.
|
|
6
|
+
* Waits for the daemon to finish analysis, then exits with code 2 (blocking
|
|
7
|
+
* feedback) if the file rating falls below the configured minimum — forcing
|
|
8
|
+
* Claude Code to surface the violations before the agent can continue.
|
|
9
|
+
*/
|
|
10
|
+
import { FileAnalysis, HookPayload, SessionCreatePayload } from './types';
|
|
11
|
+
interface AnalyzeResponse {
|
|
12
|
+
analysis: FileAnalysis | null;
|
|
13
|
+
minRating: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const WATCHED_EXTENSIONS: Set<string>;
|
|
16
|
+
/** Convert a simple glob pattern to a RegExp */
|
|
17
|
+
export declare function globToRegex(pattern: string): RegExp;
|
|
18
|
+
export declare function isFileExcludedByScanConfig(filePath: string, ext: string): boolean;
|
|
19
|
+
export declare function main(): Promise<void>;
|
|
20
|
+
export declare function readStdin(): Promise<HookPayload | null>;
|
|
21
|
+
export declare function ensureDaemonRunning(): Promise<void>;
|
|
22
|
+
export declare function isDaemonAlive(): boolean;
|
|
23
|
+
export declare function isSessionRegistered(sessionId: string): boolean;
|
|
24
|
+
export declare function markSessionRegistered(sessionId: string): void;
|
|
25
|
+
export declare function findGitRoot(dir: string): string;
|
|
26
|
+
export declare function sendToDaemon(filePath: string): Promise<AnalyzeResponse | null>;
|
|
27
|
+
export declare function registerRepository(sessionPayload: SessionCreatePayload): Promise<void>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=hook-receiver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-receiver.d.ts","sourceRoot":"","sources":["../src/hook-receiver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAU,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAElF,UAAU,eAAe;IACvB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,eAAO,MAAM,kBAAkB,aAAiD,CAAC;AAIjF,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYnD;AAYD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAcjF;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAoF1C;AAED,wBAAgB,SAAS,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAevD;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAczD;AAED,wBAAgB,aAAa,IAAI,OAAO,CASvC;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAM9D;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAK7D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAgC9E;AAMD,wBAAsB,kBAAkB,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC5F"}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* gate-keeper hook-receiver
|
|
4
|
+
*
|
|
5
|
+
* Called by Claude Code's PostToolUse hook on every Write/Edit operation,
|
|
6
|
+
* and also on session_create events to register new repos.
|
|
7
|
+
* Waits for the daemon to finish analysis, then exits with code 2 (blocking
|
|
8
|
+
* feedback) if the file rating falls below the configured minimum — forcing
|
|
9
|
+
* Claude Code to surface the violations before the agent can continue.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.WATCHED_EXTENSIONS = void 0;
|
|
46
|
+
exports.globToRegex = globToRegex;
|
|
47
|
+
exports.isFileExcludedByScanConfig = isFileExcludedByScanConfig;
|
|
48
|
+
exports.main = main;
|
|
49
|
+
exports.readStdin = readStdin;
|
|
50
|
+
exports.ensureDaemonRunning = ensureDaemonRunning;
|
|
51
|
+
exports.isDaemonAlive = isDaemonAlive;
|
|
52
|
+
exports.isSessionRegistered = isSessionRegistered;
|
|
53
|
+
exports.markSessionRegistered = markSessionRegistered;
|
|
54
|
+
exports.findGitRoot = findGitRoot;
|
|
55
|
+
exports.sendToDaemon = sendToDaemon;
|
|
56
|
+
exports.registerRepository = registerRepository;
|
|
57
|
+
const http = __importStar(require("http"));
|
|
58
|
+
const fs = __importStar(require("fs"));
|
|
59
|
+
const path = __importStar(require("path"));
|
|
60
|
+
const child_process_1 = require("child_process");
|
|
61
|
+
const IPC_PORT = 5379;
|
|
62
|
+
const GK_DIR = path.join(process.env.HOME ?? '/tmp', '.gate-keeper');
|
|
63
|
+
const PID_FILE = path.join(GK_DIR, 'daemon.pid');
|
|
64
|
+
const SESSIONS_DIR = path.join(GK_DIR, 'sessions');
|
|
65
|
+
const DAEMON_SCRIPT = path.join(__dirname, 'daemon.js');
|
|
66
|
+
exports.WATCHED_EXTENSIONS = new Set(['.ts', '.tsx', '.jsx', '.js', '.cs']);
|
|
67
|
+
const CONFIG_FILE = path.join(GK_DIR, 'config.json');
|
|
68
|
+
/** Convert a simple glob pattern to a RegExp */
|
|
69
|
+
function globToRegex(pattern) {
|
|
70
|
+
const escaped = pattern
|
|
71
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
72
|
+
.replace(/\*\*/g, '__GLOBSTAR__')
|
|
73
|
+
.replace(/\*/g, '[^/]*');
|
|
74
|
+
// Handle **/ at the start - it should match zero or more directories
|
|
75
|
+
const processed = escaped.replace(/^__GLOBSTAR__\//, '(?:.*/)?');
|
|
76
|
+
// Handle **/ in the middle - replace with .*
|
|
77
|
+
const final = processed.replace(/__GLOBSTAR__/g, '.*');
|
|
78
|
+
return new RegExp(final, 'i');
|
|
79
|
+
}
|
|
80
|
+
function loadScanExcludePatterns() {
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
83
|
+
const raw = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
84
|
+
return raw.scanExcludePatterns;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch { }
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
function isFileExcludedByScanConfig(filePath, ext) {
|
|
91
|
+
const patterns = loadScanExcludePatterns();
|
|
92
|
+
if (!patterns)
|
|
93
|
+
return false;
|
|
94
|
+
const fileName = filePath.split('/').pop() ?? filePath;
|
|
95
|
+
const langKey = ext === '.cs' ? 'csharp' : ['.ts', '.tsx', '.jsx', '.js'].includes(ext) ? 'typescript' : null;
|
|
96
|
+
const allPatterns = [
|
|
97
|
+
...(patterns.global ?? []),
|
|
98
|
+
...(langKey ? (patterns[langKey] ?? []) : []),
|
|
99
|
+
];
|
|
100
|
+
return allPatterns.some(p => {
|
|
101
|
+
const re = globToRegex(p);
|
|
102
|
+
return re.test(filePath) || re.test(fileName);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async function main() {
|
|
106
|
+
const payload = await readStdin();
|
|
107
|
+
if (!payload)
|
|
108
|
+
return;
|
|
109
|
+
// Handle session_create events (VS Code / GitHub Copilot task)
|
|
110
|
+
if (payload.hook_event_name === 'session_create') {
|
|
111
|
+
const sessionPayload = payload;
|
|
112
|
+
await ensureDaemonRunning();
|
|
113
|
+
await registerRepository(sessionPayload);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Handle Claude Code SessionStart — fires exactly once when a new session begins
|
|
117
|
+
if (payload.hook_event_name === 'SessionStart') {
|
|
118
|
+
const sessionId = payload.session_id;
|
|
119
|
+
const cwd = payload.cwd;
|
|
120
|
+
if (sessionId && cwd) {
|
|
121
|
+
await ensureDaemonRunning();
|
|
122
|
+
const gitRoot = findGitRoot(cwd);
|
|
123
|
+
await registerRepository({
|
|
124
|
+
session_id: sessionId,
|
|
125
|
+
hook_event_name: 'session_create',
|
|
126
|
+
tool_name: 'claude',
|
|
127
|
+
session_info: {
|
|
128
|
+
workspace_path: cwd,
|
|
129
|
+
git_root: gitRoot,
|
|
130
|
+
session_type: 'claude'
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Handle Claude Code session start — fires on every user prompt, deduplicated by session_id
|
|
137
|
+
if (payload.hook_event_name === 'UserPromptSubmit') {
|
|
138
|
+
const sessionId = payload.session_id;
|
|
139
|
+
const cwd = payload.cwd;
|
|
140
|
+
if (sessionId && cwd && !isSessionRegistered(sessionId)) {
|
|
141
|
+
markSessionRegistered(sessionId);
|
|
142
|
+
await ensureDaemonRunning();
|
|
143
|
+
const gitRoot = findGitRoot(cwd);
|
|
144
|
+
await registerRepository({
|
|
145
|
+
session_id: sessionId,
|
|
146
|
+
hook_event_name: 'session_create',
|
|
147
|
+
tool_name: 'claude',
|
|
148
|
+
session_info: {
|
|
149
|
+
workspace_path: cwd,
|
|
150
|
+
git_root: gitRoot,
|
|
151
|
+
session_type: 'claude'
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Handle file analysis on Write/Edit
|
|
158
|
+
const filePath = payload.tool_input?.file_path ?? payload.tool_input?.path;
|
|
159
|
+
if (!filePath)
|
|
160
|
+
return;
|
|
161
|
+
const ext = path.extname(filePath);
|
|
162
|
+
if (!exports.WATCHED_EXTENSIONS.has(ext))
|
|
163
|
+
return;
|
|
164
|
+
// Check scan exclude patterns from config — skip excluded files early
|
|
165
|
+
if (isFileExcludedByScanConfig(filePath, ext))
|
|
166
|
+
return;
|
|
167
|
+
await ensureDaemonRunning();
|
|
168
|
+
const result = await sendToDaemon(filePath);
|
|
169
|
+
if (!result?.analysis)
|
|
170
|
+
return;
|
|
171
|
+
const { analysis, minRating } = result;
|
|
172
|
+
if (analysis.rating < minRating) {
|
|
173
|
+
const lines = [
|
|
174
|
+
`[Gate Keeper] ${path.basename(filePath)} rated ${analysis.rating}/10 (minimum ${minRating}/10) — fix violations before proceeding:`,
|
|
175
|
+
];
|
|
176
|
+
for (const v of analysis.violations) {
|
|
177
|
+
const loc = v.line != null ? ` (line ${v.line})` : '';
|
|
178
|
+
const fix = v.fix ? ` — ${v.fix}` : '';
|
|
179
|
+
lines.push(` [${v.severity}] ${v.message}${loc}${fix}`);
|
|
180
|
+
}
|
|
181
|
+
lines.push(`\nRaise the rating to at least ${minRating}/10 before moving on.`);
|
|
182
|
+
process.stdout.write(lines.join('\n') + '\n');
|
|
183
|
+
process.exit(2);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function readStdin() {
|
|
187
|
+
return new Promise(resolve => {
|
|
188
|
+
let data = '';
|
|
189
|
+
process.stdin.setEncoding('utf8');
|
|
190
|
+
process.stdin.on('data', chunk => (data += chunk));
|
|
191
|
+
process.stdin.on('end', () => {
|
|
192
|
+
try {
|
|
193
|
+
resolve(JSON.parse(data));
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
resolve(null);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
// Don't block if stdin never closes
|
|
200
|
+
setTimeout(() => resolve(null), 2000);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
async function ensureDaemonRunning() {
|
|
204
|
+
if (isDaemonAlive())
|
|
205
|
+
return;
|
|
206
|
+
if (!fs.existsSync(DAEMON_SCRIPT))
|
|
207
|
+
return;
|
|
208
|
+
const child = (0, child_process_1.spawn)(process.execPath, [DAEMON_SCRIPT], {
|
|
209
|
+
detached: true,
|
|
210
|
+
stdio: 'ignore',
|
|
211
|
+
env: { ...process.env }
|
|
212
|
+
});
|
|
213
|
+
child.unref();
|
|
214
|
+
// Give the daemon a moment to bind its port
|
|
215
|
+
await sleep(300);
|
|
216
|
+
}
|
|
217
|
+
function isDaemonAlive() {
|
|
218
|
+
try {
|
|
219
|
+
const pid = parseInt(fs.readFileSync(PID_FILE, 'utf8').trim(), 10);
|
|
220
|
+
if (isNaN(pid))
|
|
221
|
+
return false;
|
|
222
|
+
process.kill(pid, 0); // throws if process doesn't exist
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function isSessionRegistered(sessionId) {
|
|
230
|
+
try {
|
|
231
|
+
return fs.existsSync(path.join(SESSIONS_DIR, sessionId));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function markSessionRegistered(sessionId) {
|
|
238
|
+
try {
|
|
239
|
+
fs.mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
240
|
+
fs.writeFileSync(path.join(SESSIONS_DIR, sessionId), String(Date.now()));
|
|
241
|
+
}
|
|
242
|
+
catch { }
|
|
243
|
+
}
|
|
244
|
+
function findGitRoot(dir) {
|
|
245
|
+
const result = (0, child_process_1.spawnSync)('git', ['rev-parse', '--show-toplevel'], {
|
|
246
|
+
cwd: dir, encoding: 'utf8', timeout: 3000
|
|
247
|
+
});
|
|
248
|
+
return (result.status === 0 && result.stdout.trim()) ? result.stdout.trim() : dir;
|
|
249
|
+
}
|
|
250
|
+
function sendToDaemon(filePath) {
|
|
251
|
+
const repoRoot = findGitRoot(path.dirname(filePath));
|
|
252
|
+
return new Promise(resolve => {
|
|
253
|
+
const body = JSON.stringify({ filePath, repoRoot });
|
|
254
|
+
const req = http.request({
|
|
255
|
+
hostname: '127.0.0.1',
|
|
256
|
+
port: IPC_PORT,
|
|
257
|
+
path: '/analyze',
|
|
258
|
+
method: 'POST',
|
|
259
|
+
headers: {
|
|
260
|
+
'Content-Type': 'application/json',
|
|
261
|
+
'Content-Length': Buffer.byteLength(body)
|
|
262
|
+
}
|
|
263
|
+
}, res => {
|
|
264
|
+
let data = '';
|
|
265
|
+
res.setEncoding('utf8');
|
|
266
|
+
res.on('data', chunk => (data += chunk));
|
|
267
|
+
res.on('end', () => {
|
|
268
|
+
try {
|
|
269
|
+
resolve(JSON.parse(data));
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
resolve(null);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
req.on('error', () => resolve(null));
|
|
277
|
+
// Analysis can take a few seconds for large files — generous timeout so we
|
|
278
|
+
// don't silently drop the gate on slow machines.
|
|
279
|
+
req.setTimeout(8000, () => { req.destroy(); resolve(null); });
|
|
280
|
+
req.write(body);
|
|
281
|
+
req.end();
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function sleep(ms) {
|
|
285
|
+
return new Promise(r => setTimeout(r, ms));
|
|
286
|
+
}
|
|
287
|
+
async function registerRepository(sessionPayload) {
|
|
288
|
+
const workspacePath = sessionPayload.session_info.workspace_path;
|
|
289
|
+
const gitRoot = sessionPayload.session_info.git_root || findGitRoot(workspacePath);
|
|
290
|
+
const sessionType = sessionPayload.session_info.session_type || 'unknown';
|
|
291
|
+
const body = JSON.stringify({
|
|
292
|
+
action: 'register_repo',
|
|
293
|
+
repo: {
|
|
294
|
+
path: gitRoot,
|
|
295
|
+
name: path.basename(gitRoot) || gitRoot,
|
|
296
|
+
sessionId: sessionPayload.session_id,
|
|
297
|
+
sessionType,
|
|
298
|
+
createdAt: Date.now()
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
return new Promise(resolve => {
|
|
302
|
+
const req = http.request({
|
|
303
|
+
hostname: '127.0.0.1',
|
|
304
|
+
port: IPC_PORT,
|
|
305
|
+
path: '/repo-register',
|
|
306
|
+
method: 'POST',
|
|
307
|
+
headers: {
|
|
308
|
+
'Content-Type': 'application/json',
|
|
309
|
+
'Content-Length': Buffer.byteLength(body)
|
|
310
|
+
}
|
|
311
|
+
}, res => {
|
|
312
|
+
let data = '';
|
|
313
|
+
res.setEncoding('utf8');
|
|
314
|
+
res.on('data', chunk => (data += chunk));
|
|
315
|
+
res.on('end', () => resolve());
|
|
316
|
+
});
|
|
317
|
+
req.on('error', () => resolve());
|
|
318
|
+
req.setTimeout(5000, () => { req.destroy(); resolve(); });
|
|
319
|
+
req.write(body);
|
|
320
|
+
req.end();
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
// Only run main() when this script is executed directly (not during tests/imports)
|
|
324
|
+
if (require.main === module) {
|
|
325
|
+
main().catch(() => { }).finally(() => process.exit(0));
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=hook-receiver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-receiver.js","sourceRoot":"","sources":["../src/hook-receiver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git hook script generator.
|
|
3
|
+
*
|
|
4
|
+
* Produces shell scripts for post-commit, post-checkout, and the graphify
|
|
5
|
+
* merge driver. Scripts are designed to be written into .git/hooks/ and
|
|
6
|
+
* made executable. They trigger gate-keeper analysis after commits/checkouts
|
|
7
|
+
* without blocking the git operation.
|
|
8
|
+
*/
|
|
9
|
+
export interface HookInstallResult {
|
|
10
|
+
hook: string;
|
|
11
|
+
path: string;
|
|
12
|
+
action: 'created' | 'updated' | 'skipped';
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
/** Shell script that re-analyzes changed files via the daemon (if running) */
|
|
16
|
+
export declare function postCommitScript(gateKeeperDir: string): string;
|
|
17
|
+
/** Shell script that triggers a full re-scan after branch checkout */
|
|
18
|
+
export declare function postCheckoutScript(gateKeeperDir: string): string;
|
|
19
|
+
/** Git merge driver that union-merges graph JSON files */
|
|
20
|
+
export declare function mergeDriverScript(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Install git hooks into a repository's .git/hooks/ directory.
|
|
23
|
+
* Returns one result entry per hook.
|
|
24
|
+
*/
|
|
25
|
+
export declare function installGitHooks(repoRoot: string, gateKeeperDir: string, force?: boolean): HookInstallResult[];
|
|
26
|
+
/** Generate the .gitattributes line for the graph merge driver */
|
|
27
|
+
export declare function gitAttributesEntry(): string;
|
|
28
|
+
/** Generate the .git/config snippet for the merge driver */
|
|
29
|
+
export declare function gitConfigEntry(gateKeeperDir: string): string;
|
|
30
|
+
//# sourceMappingURL=git-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-hooks.d.ts","sourceRoot":"","sources":["../../src/hooks/git-hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAmB9D;AAED,sEAAsE;AACtE,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CA2BhE;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,IAAI,MAAM,CAwC1C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,KAAK,UAAQ,GACZ,iBAAiB,EAAE,CA2BrB;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,4DAA4D;AAC5D,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAG5D"}
|