@codacy/gate-cli 0.14.0 → 0.14.2
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/bin/gate.js +193 -99
- package/package.json +1 -1
package/bin/gate.js
CHANGED
|
@@ -10355,6 +10355,9 @@ var ITERATION_FILE = `${GATE_DIR}/.iteration-count`;
|
|
|
10355
10355
|
var HASH_FILE = `${GATE_DIR}/.last-pass-hash`;
|
|
10356
10356
|
var INTENT_FILE = `${GATE_DIR}/.last-intent`;
|
|
10357
10357
|
var CACHE_DIR = `${GATE_DIR}/.cache`;
|
|
10358
|
+
var DEBUG_LOG_DIR = `${GATE_DIR}/.logs`;
|
|
10359
|
+
var DEBUG_LOG_FILE = `${DEBUG_LOG_DIR}/cli.log`;
|
|
10360
|
+
var DEBUG_LOG_MAX_BYTES = 1048576;
|
|
10358
10361
|
var GATE_MD_FILE = "GATE.md";
|
|
10359
10362
|
var CLAUDE_SETTINGS_FILE = ".claude/settings.json";
|
|
10360
10363
|
var STANDARD_FILE = `${GATE_DIR}/standard.yaml`;
|
|
@@ -10588,9 +10591,43 @@ function printVerbose(msg, verbose) {
|
|
|
10588
10591
|
}
|
|
10589
10592
|
}
|
|
10590
10593
|
|
|
10594
|
+
// src/lib/debug-log.ts
|
|
10595
|
+
var import_node_fs = require("node:fs");
|
|
10596
|
+
function isEnabled() {
|
|
10597
|
+
const v = process.env.GATE_DEBUG;
|
|
10598
|
+
if (v === "0" || v === "false" || v === "off") return false;
|
|
10599
|
+
return true;
|
|
10600
|
+
}
|
|
10601
|
+
function logHttpCall(entry) {
|
|
10602
|
+
if (!isEnabled()) return;
|
|
10603
|
+
writeLine({ ts: (/* @__PURE__ */ new Date()).toISOString(), kind: "http", ...entry });
|
|
10604
|
+
}
|
|
10605
|
+
function logEvent(event, data) {
|
|
10606
|
+
if (!isEnabled()) return;
|
|
10607
|
+
writeLine({ ts: (/* @__PURE__ */ new Date()).toISOString(), kind: "event", event, ...data ?? {} });
|
|
10608
|
+
}
|
|
10609
|
+
function writeLine(obj) {
|
|
10610
|
+
try {
|
|
10611
|
+
const dir = projectPath(DEBUG_LOG_DIR);
|
|
10612
|
+
const file = projectPath(DEBUG_LOG_FILE);
|
|
10613
|
+
(0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
10614
|
+
rotateIfNeeded(file);
|
|
10615
|
+
(0, import_node_fs.appendFileSync)(file, JSON.stringify(obj) + "\n");
|
|
10616
|
+
} catch {
|
|
10617
|
+
}
|
|
10618
|
+
}
|
|
10619
|
+
function rotateIfNeeded(file) {
|
|
10620
|
+
try {
|
|
10621
|
+
const s = (0, import_node_fs.statSync)(file);
|
|
10622
|
+
if (s.size < DEBUG_LOG_MAX_BYTES) return;
|
|
10623
|
+
(0, import_node_fs.renameSync)(file, `${file}.1`);
|
|
10624
|
+
} catch {
|
|
10625
|
+
}
|
|
10626
|
+
}
|
|
10627
|
+
|
|
10591
10628
|
// src/lib/api-client.ts
|
|
10592
10629
|
async function apiRequest(options) {
|
|
10593
|
-
const { method, path, serviceUrl, token, body, verbose, timeout = 9e4 } = options;
|
|
10630
|
+
const { method, path, serviceUrl, token, body, verbose, timeout = 9e4, cmd = "unknown", retry = false } = options;
|
|
10594
10631
|
const url = `${serviceUrl}${path}`;
|
|
10595
10632
|
const headers = {
|
|
10596
10633
|
"Content-Type": "application/json"
|
|
@@ -10599,36 +10636,67 @@ async function apiRequest(options) {
|
|
|
10599
10636
|
headers["Authorization"] = `Bearer ${token}`;
|
|
10600
10637
|
}
|
|
10601
10638
|
printVerbose(`${method} ${url}`, verbose);
|
|
10639
|
+
const serializedBody = body ? JSON.stringify(body) : void 0;
|
|
10602
10640
|
if (body) {
|
|
10603
|
-
printVerbose(`Body: ${
|
|
10641
|
+
printVerbose(`Body: ${serializedBody.slice(0, 500)}`, verbose);
|
|
10604
10642
|
}
|
|
10643
|
+
const startedAt = Date.now();
|
|
10644
|
+
const bodyBytes = serializedBody ? Buffer.byteLength(serializedBody) : 0;
|
|
10645
|
+
const logBase = { cmd, method, url, body_bytes: bodyBytes, retry };
|
|
10605
10646
|
let response;
|
|
10606
10647
|
try {
|
|
10607
10648
|
response = await fetch(url, {
|
|
10608
10649
|
method,
|
|
10609
10650
|
headers,
|
|
10610
|
-
body:
|
|
10651
|
+
body: serializedBody,
|
|
10611
10652
|
signal: AbortSignal.timeout(timeout)
|
|
10612
10653
|
});
|
|
10613
10654
|
} catch (err) {
|
|
10614
|
-
|
|
10615
|
-
|
|
10616
|
-
|
|
10617
|
-
|
|
10655
|
+
const duration2 = Date.now() - startedAt;
|
|
10656
|
+
const isTimeout = err instanceof DOMException && err.name === "TimeoutError";
|
|
10657
|
+
const category = isTimeout ? "timeout" : "network";
|
|
10658
|
+
const error = isTimeout ? `Request timed out after ${timeout}ms` : `Network error: ${err.message}`;
|
|
10659
|
+
logHttpCall({ ...logBase, duration_ms: duration2, http_status: null, category, error });
|
|
10660
|
+
return { ok: false, error, category };
|
|
10618
10661
|
}
|
|
10619
10662
|
let data;
|
|
10620
10663
|
try {
|
|
10621
10664
|
data = await response.json();
|
|
10622
10665
|
} catch {
|
|
10623
|
-
|
|
10666
|
+
const duration2 = Date.now() - startedAt;
|
|
10667
|
+
const error = `Invalid JSON response (HTTP ${response.status})`;
|
|
10668
|
+
logHttpCall({
|
|
10669
|
+
...logBase,
|
|
10670
|
+
duration_ms: duration2,
|
|
10671
|
+
http_status: response.status,
|
|
10672
|
+
category: "invalid_json",
|
|
10673
|
+
error
|
|
10674
|
+
});
|
|
10675
|
+
return { ok: false, error, category: "invalid_json" };
|
|
10624
10676
|
}
|
|
10625
10677
|
printVerbose(`Response ${response.status}: ${JSON.stringify(data).slice(0, 500)}`, verbose);
|
|
10678
|
+
const duration = Date.now() - startedAt;
|
|
10626
10679
|
if (!response.ok) {
|
|
10627
10680
|
const apiErr = data;
|
|
10628
10681
|
const code = apiErr?.error?.code ?? "UNKNOWN";
|
|
10629
10682
|
const message = apiErr?.error?.message ?? `HTTP ${response.status}`;
|
|
10630
|
-
|
|
10683
|
+
const category = response.status >= 500 ? "http_5xx" : "http_4xx";
|
|
10684
|
+
const error = `${code}: ${message}`;
|
|
10685
|
+
logHttpCall({
|
|
10686
|
+
...logBase,
|
|
10687
|
+
duration_ms: duration,
|
|
10688
|
+
http_status: response.status,
|
|
10689
|
+
category,
|
|
10690
|
+
error
|
|
10691
|
+
});
|
|
10692
|
+
return { ok: false, error, category };
|
|
10631
10693
|
}
|
|
10694
|
+
logHttpCall({
|
|
10695
|
+
...logBase,
|
|
10696
|
+
duration_ms: duration,
|
|
10697
|
+
http_status: response.status,
|
|
10698
|
+
category: "ok"
|
|
10699
|
+
});
|
|
10632
10700
|
return { ok: true, data };
|
|
10633
10701
|
}
|
|
10634
10702
|
|
|
@@ -10858,7 +10926,7 @@ function registerHooksCommands(program2) {
|
|
|
10858
10926
|
|
|
10859
10927
|
// src/lib/conversation-buffer.ts
|
|
10860
10928
|
var import_promises5 = require("node:fs/promises");
|
|
10861
|
-
var
|
|
10929
|
+
var import_node_fs2 = require("node:fs");
|
|
10862
10930
|
var import_node_child_process4 = require("node:child_process");
|
|
10863
10931
|
function stripImageReferences(text) {
|
|
10864
10932
|
return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
|
|
@@ -10890,7 +10958,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
10890
10958
|
}
|
|
10891
10959
|
async function readAndClearConversationBuffer() {
|
|
10892
10960
|
try {
|
|
10893
|
-
if ((0,
|
|
10961
|
+
if ((0, import_node_fs2.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
10894
10962
|
const entries = await readBufferEntries();
|
|
10895
10963
|
await (0, import_promises5.unlink)(CONVERSATION_BUFFER_FILE).catch(() => {
|
|
10896
10964
|
});
|
|
@@ -10901,7 +10969,7 @@ async function readAndClearConversationBuffer() {
|
|
|
10901
10969
|
};
|
|
10902
10970
|
}
|
|
10903
10971
|
}
|
|
10904
|
-
if ((0,
|
|
10972
|
+
if ((0, import_node_fs2.existsSync)(INTENT_FILE)) {
|
|
10905
10973
|
try {
|
|
10906
10974
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
10907
10975
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -10957,12 +11025,12 @@ function getRecentCommitMessages() {
|
|
|
10957
11025
|
}
|
|
10958
11026
|
|
|
10959
11027
|
// src/commands/intent.ts
|
|
10960
|
-
var
|
|
11028
|
+
var import_node_fs3 = require("node:fs");
|
|
10961
11029
|
function registerIntentCommands(program2) {
|
|
10962
11030
|
const intent = program2.command("intent").description("Manage intent capture");
|
|
10963
11031
|
intent.command("capture").description("Capture user intent from stdin (used by UserPromptSubmit hook)").action(async () => {
|
|
10964
11032
|
try {
|
|
10965
|
-
if (!(0,
|
|
11033
|
+
if (!(0, import_node_fs3.existsSync)(GATE_DIR)) {
|
|
10966
11034
|
process.exit(0);
|
|
10967
11035
|
}
|
|
10968
11036
|
const chunks = [];
|
|
@@ -11301,17 +11369,17 @@ function registerFeedbackCommand(program2) {
|
|
|
11301
11369
|
|
|
11302
11370
|
// src/lib/git.ts
|
|
11303
11371
|
var import_node_child_process5 = require("node:child_process");
|
|
11304
|
-
var
|
|
11372
|
+
var import_node_fs4 = require("node:fs");
|
|
11305
11373
|
var import_node_path4 = require("node:path");
|
|
11306
11374
|
function resolveFile(relpath) {
|
|
11307
|
-
if ((0,
|
|
11308
|
-
if ((0,
|
|
11375
|
+
if ((0, import_node_fs4.existsSync)(relpath)) return relpath;
|
|
11376
|
+
if ((0, import_node_fs4.existsSync)(".claude/worktrees")) {
|
|
11309
11377
|
try {
|
|
11310
|
-
const entries = (0,
|
|
11378
|
+
const entries = (0, import_node_fs4.readdirSync)(".claude/worktrees", { withFileTypes: true });
|
|
11311
11379
|
for (const entry of entries) {
|
|
11312
11380
|
if (!entry.isDirectory()) continue;
|
|
11313
11381
|
const candidate = (0, import_node_path4.join)(".claude/worktrees", entry.name, relpath);
|
|
11314
|
-
if ((0,
|
|
11382
|
+
if ((0, import_node_fs4.existsSync)(candidate)) return candidate;
|
|
11315
11383
|
}
|
|
11316
11384
|
} catch {
|
|
11317
11385
|
}
|
|
@@ -11363,10 +11431,10 @@ function getChangedFiles() {
|
|
|
11363
11431
|
function getWorktreeFiles() {
|
|
11364
11432
|
const result = [];
|
|
11365
11433
|
const worktreeDir = ".claude/worktrees";
|
|
11366
|
-
if (!(0,
|
|
11434
|
+
if (!(0, import_node_fs4.existsSync)(worktreeDir)) return result;
|
|
11367
11435
|
try {
|
|
11368
11436
|
const fiveMinAgo = Date.now() - 5 * 60 * 1e3;
|
|
11369
|
-
const entries = (0,
|
|
11437
|
+
const entries = (0, import_node_fs4.readdirSync)(worktreeDir, { withFileTypes: true });
|
|
11370
11438
|
for (const entry of entries) {
|
|
11371
11439
|
if (!entry.isDirectory()) continue;
|
|
11372
11440
|
const wtDir = (0, import_node_path4.join)(worktreeDir, entry.name);
|
|
@@ -11378,7 +11446,7 @@ function getWorktreeFiles() {
|
|
|
11378
11446
|
}
|
|
11379
11447
|
function scanDir(baseDir, dir, minMtime, result) {
|
|
11380
11448
|
try {
|
|
11381
|
-
const entries = (0,
|
|
11449
|
+
const entries = (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true });
|
|
11382
11450
|
for (const entry of entries) {
|
|
11383
11451
|
const fullPath = (0, import_node_path4.join)(dir, entry.name);
|
|
11384
11452
|
if (entry.isDirectory()) {
|
|
@@ -11388,7 +11456,7 @@ function scanDir(baseDir, dir, minMtime, result) {
|
|
|
11388
11456
|
const ext = (0, import_node_path4.extname)(entry.name).slice(1);
|
|
11389
11457
|
if (!ANALYZABLE_EXTENSIONS.has(ext)) continue;
|
|
11390
11458
|
try {
|
|
11391
|
-
const stat = (0,
|
|
11459
|
+
const stat = (0, import_node_fs4.statSync)(fullPath);
|
|
11392
11460
|
if (stat.mtimeMs >= minMtime) {
|
|
11393
11461
|
const relPath = fullPath.slice(baseDir.length + 1);
|
|
11394
11462
|
result.push(relPath);
|
|
@@ -11427,7 +11495,7 @@ function getCurrentCommit() {
|
|
|
11427
11495
|
}
|
|
11428
11496
|
|
|
11429
11497
|
// src/lib/files.ts
|
|
11430
|
-
var
|
|
11498
|
+
var import_node_fs5 = require("node:fs");
|
|
11431
11499
|
var import_node_path5 = require("node:path");
|
|
11432
11500
|
var LANG_MAP = {
|
|
11433
11501
|
// Analyzable (static analysis + Gemini)
|
|
@@ -11504,7 +11572,7 @@ function sortByMtime(files) {
|
|
|
11504
11572
|
const resolved = resolveFile(f);
|
|
11505
11573
|
if (!resolved) return null;
|
|
11506
11574
|
try {
|
|
11507
|
-
const stat = (0,
|
|
11575
|
+
const stat = (0, import_node_fs5.statSync)(resolved);
|
|
11508
11576
|
return { path: f, resolved, mtime: stat.mtimeMs };
|
|
11509
11577
|
} catch {
|
|
11510
11578
|
return null;
|
|
@@ -11526,7 +11594,7 @@ function collectCodeDelta(files, opts) {
|
|
|
11526
11594
|
if (!resolved) continue;
|
|
11527
11595
|
let size;
|
|
11528
11596
|
try {
|
|
11529
|
-
size = (0,
|
|
11597
|
+
size = (0, import_node_fs5.statSync)(resolved).size;
|
|
11530
11598
|
} catch {
|
|
11531
11599
|
continue;
|
|
11532
11600
|
}
|
|
@@ -11534,7 +11602,7 @@ function collectCodeDelta(files, opts) {
|
|
|
11534
11602
|
if (totalSize + size > maxTotalBytes) break;
|
|
11535
11603
|
let content;
|
|
11536
11604
|
try {
|
|
11537
|
-
content = (0,
|
|
11605
|
+
content = (0, import_node_fs5.readFileSync)(resolved, "utf-8");
|
|
11538
11606
|
} catch {
|
|
11539
11607
|
continue;
|
|
11540
11608
|
}
|
|
@@ -11557,12 +11625,12 @@ function collectCodeDelta(files, opts) {
|
|
|
11557
11625
|
}
|
|
11558
11626
|
|
|
11559
11627
|
// src/lib/debounce.ts
|
|
11560
|
-
var
|
|
11628
|
+
var import_node_fs6 = require("node:fs");
|
|
11561
11629
|
var import_node_crypto = require("node:crypto");
|
|
11562
11630
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS) {
|
|
11563
|
-
if (!(0,
|
|
11631
|
+
if (!(0, import_node_fs6.existsSync)(DEBOUNCE_FILE)) return null;
|
|
11564
11632
|
try {
|
|
11565
|
-
const lastTs = parseInt((0,
|
|
11633
|
+
const lastTs = parseInt((0, import_node_fs6.readFileSync)(DEBOUNCE_FILE, "utf-8").trim(), 10);
|
|
11566
11634
|
const nowTs = Math.floor(Date.now() / 1e3);
|
|
11567
11635
|
const elapsed = nowTs - lastTs;
|
|
11568
11636
|
if (elapsed < debounceSeconds) {
|
|
@@ -11574,10 +11642,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS) {
|
|
|
11574
11642
|
}
|
|
11575
11643
|
function checkMtime(files, bypassForRecentCommits) {
|
|
11576
11644
|
if (bypassForRecentCommits) return null;
|
|
11577
|
-
if (!(0,
|
|
11645
|
+
if (!(0, import_node_fs6.existsSync)(DEBOUNCE_FILE)) return null;
|
|
11578
11646
|
let debounceTime;
|
|
11579
11647
|
try {
|
|
11580
|
-
debounceTime = (0,
|
|
11648
|
+
debounceTime = (0, import_node_fs6.statSync)(DEBOUNCE_FILE).mtimeMs;
|
|
11581
11649
|
} catch {
|
|
11582
11650
|
return null;
|
|
11583
11651
|
}
|
|
@@ -11585,7 +11653,7 @@ function checkMtime(files, bypassForRecentCommits) {
|
|
|
11585
11653
|
const resolved = resolveFile(f);
|
|
11586
11654
|
if (!resolved) continue;
|
|
11587
11655
|
try {
|
|
11588
|
-
const stat = (0,
|
|
11656
|
+
const stat = (0, import_node_fs6.statSync)(resolved);
|
|
11589
11657
|
if (stat.mtimeMs > debounceTime) {
|
|
11590
11658
|
return null;
|
|
11591
11659
|
}
|
|
@@ -11601,8 +11669,8 @@ function computeContentHash(files) {
|
|
|
11601
11669
|
for (const f of sorted) {
|
|
11602
11670
|
const resolved = resolveFile(f) ?? f;
|
|
11603
11671
|
try {
|
|
11604
|
-
if ((0,
|
|
11605
|
-
hash.update((0,
|
|
11672
|
+
if ((0, import_node_fs6.existsSync)(resolved)) {
|
|
11673
|
+
hash.update((0, import_node_fs6.readFileSync)(resolved));
|
|
11606
11674
|
}
|
|
11607
11675
|
} catch {
|
|
11608
11676
|
}
|
|
@@ -11611,9 +11679,9 @@ function computeContentHash(files) {
|
|
|
11611
11679
|
}
|
|
11612
11680
|
function checkContentHash(files) {
|
|
11613
11681
|
const hash = computeContentHash(files);
|
|
11614
|
-
if ((0,
|
|
11682
|
+
if ((0, import_node_fs6.existsSync)(HASH_FILE)) {
|
|
11615
11683
|
try {
|
|
11616
|
-
const storedHash = (0,
|
|
11684
|
+
const storedHash = (0, import_node_fs6.readFileSync)(HASH_FILE, "utf-8").trim();
|
|
11617
11685
|
if (hash === storedHash) {
|
|
11618
11686
|
return { skip: "No source changes since last analysis", hash };
|
|
11619
11687
|
}
|
|
@@ -11623,23 +11691,23 @@ function checkContentHash(files) {
|
|
|
11623
11691
|
return { skip: null, hash };
|
|
11624
11692
|
}
|
|
11625
11693
|
function recordAnalysisStart() {
|
|
11626
|
-
(0,
|
|
11627
|
-
(0,
|
|
11694
|
+
(0, import_node_fs6.mkdirSync)(GATE_DIR, { recursive: true });
|
|
11695
|
+
(0, import_node_fs6.writeFileSync)(DEBOUNCE_FILE, String(Math.floor(Date.now() / 1e3)));
|
|
11628
11696
|
}
|
|
11629
11697
|
function recordPassHash(hash) {
|
|
11630
|
-
(0,
|
|
11698
|
+
(0, import_node_fs6.writeFileSync)(HASH_FILE, hash);
|
|
11631
11699
|
}
|
|
11632
11700
|
function narrowToRecent(files) {
|
|
11633
|
-
if (!(0,
|
|
11701
|
+
if (!(0, import_node_fs6.existsSync)(DEBOUNCE_FILE)) return files;
|
|
11634
11702
|
let debounceTime;
|
|
11635
11703
|
try {
|
|
11636
|
-
debounceTime = (0,
|
|
11704
|
+
debounceTime = (0, import_node_fs6.statSync)(DEBOUNCE_FILE).mtimeMs;
|
|
11637
11705
|
} catch {
|
|
11638
11706
|
return files;
|
|
11639
11707
|
}
|
|
11640
11708
|
const recent = files.filter((f) => {
|
|
11641
11709
|
try {
|
|
11642
|
-
return (0,
|
|
11710
|
+
return (0, import_node_fs6.existsSync)(f) && (0, import_node_fs6.statSync)(f).mtimeMs > debounceTime;
|
|
11643
11711
|
} catch {
|
|
11644
11712
|
return false;
|
|
11645
11713
|
}
|
|
@@ -11647,9 +11715,9 @@ function narrowToRecent(files) {
|
|
|
11647
11715
|
return recent.length > 0 ? recent : files;
|
|
11648
11716
|
}
|
|
11649
11717
|
function readIteration(currentCommit, _contentHash) {
|
|
11650
|
-
if (!(0,
|
|
11718
|
+
if (!(0, import_node_fs6.existsSync)(ITERATION_FILE)) return 1;
|
|
11651
11719
|
try {
|
|
11652
|
-
const stored = (0,
|
|
11720
|
+
const stored = (0, import_node_fs6.readFileSync)(ITERATION_FILE, "utf-8").trim();
|
|
11653
11721
|
const parts = stored.split(":");
|
|
11654
11722
|
const iter = parseInt(parts[0], 10);
|
|
11655
11723
|
const storedCommit = parts[1] ?? "";
|
|
@@ -11677,14 +11745,14 @@ function checkMaxIterations(currentCommit, maxIterations = MAX_ITERATIONS, conte
|
|
|
11677
11745
|
return { skip: null, iteration };
|
|
11678
11746
|
}
|
|
11679
11747
|
function writeIteration(iteration, commit, _contentHash) {
|
|
11680
|
-
(0,
|
|
11748
|
+
(0, import_node_fs6.mkdirSync)(GATE_DIR, { recursive: true });
|
|
11681
11749
|
const ts = Math.floor(Date.now() / 1e3);
|
|
11682
|
-
(0,
|
|
11750
|
+
(0, import_node_fs6.writeFileSync)(ITERATION_FILE, `${iteration}:${commit}:${ts}`);
|
|
11683
11751
|
}
|
|
11684
11752
|
|
|
11685
11753
|
// src/lib/static-analysis.ts
|
|
11686
11754
|
var import_node_child_process6 = require("node:child_process");
|
|
11687
|
-
var
|
|
11755
|
+
var import_node_fs7 = require("node:fs");
|
|
11688
11756
|
var SEVERITY_ORDER = {
|
|
11689
11757
|
Error: 0,
|
|
11690
11758
|
Critical: 0,
|
|
@@ -11711,7 +11779,7 @@ function runCodacyAnalysis(files) {
|
|
|
11711
11779
|
if (files.length === 0) return empty;
|
|
11712
11780
|
const existingFiles = files.filter((f) => {
|
|
11713
11781
|
try {
|
|
11714
|
-
return (0,
|
|
11782
|
+
return (0, import_node_fs7.existsSync)(f);
|
|
11715
11783
|
} catch {
|
|
11716
11784
|
return false;
|
|
11717
11785
|
}
|
|
@@ -11773,7 +11841,7 @@ function runCodacyAnalysis(files) {
|
|
|
11773
11841
|
}
|
|
11774
11842
|
|
|
11775
11843
|
// src/lib/specs.ts
|
|
11776
|
-
var
|
|
11844
|
+
var import_node_fs8 = require("node:fs");
|
|
11777
11845
|
var import_node_path6 = require("node:path");
|
|
11778
11846
|
var SPEC_CANDIDATES = [
|
|
11779
11847
|
"CLAUDE.md",
|
|
@@ -11798,15 +11866,15 @@ function discoverSpecs() {
|
|
|
11798
11866
|
if (result.length >= MAX_SPEC_FILES) return false;
|
|
11799
11867
|
if (totalBytes >= MAX_TOTAL_SPEC_BYTES) return false;
|
|
11800
11868
|
if (seen.has(specPath)) return true;
|
|
11801
|
-
if (!(0,
|
|
11869
|
+
if (!(0, import_node_fs8.existsSync)(specPath)) return true;
|
|
11802
11870
|
seen.add(specPath);
|
|
11803
11871
|
const remaining = MAX_TOTAL_SPEC_BYTES - totalBytes;
|
|
11804
11872
|
const readBytes = Math.min(MAX_SPEC_FILE_BYTES, remaining);
|
|
11805
11873
|
try {
|
|
11806
11874
|
const buf = Buffer.alloc(readBytes);
|
|
11807
|
-
const fd = (0,
|
|
11808
|
-
const bytesRead = (0,
|
|
11809
|
-
(0,
|
|
11875
|
+
const fd = (0, import_node_fs8.openSync)(specPath, "r");
|
|
11876
|
+
const bytesRead = (0, import_node_fs8.readSync)(fd, buf, 0, readBytes, 0);
|
|
11877
|
+
(0, import_node_fs8.closeSync)(fd);
|
|
11810
11878
|
const content = buf.slice(0, bytesRead).toString("utf-8");
|
|
11811
11879
|
if (!content) return true;
|
|
11812
11880
|
result.push({ path: specPath, content });
|
|
@@ -11819,7 +11887,7 @@ function discoverSpecs() {
|
|
|
11819
11887
|
if (!addSpec(candidate)) break;
|
|
11820
11888
|
}
|
|
11821
11889
|
for (const dir of ["spec", "docs"]) {
|
|
11822
|
-
if (!(0,
|
|
11890
|
+
if (!(0, import_node_fs8.existsSync)(dir)) continue;
|
|
11823
11891
|
try {
|
|
11824
11892
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
11825
11893
|
for (const mdFile of mdFiles) {
|
|
@@ -11834,7 +11902,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
11834
11902
|
if (depth >= maxDepth) return [];
|
|
11835
11903
|
const result = [];
|
|
11836
11904
|
try {
|
|
11837
|
-
const entries = (0,
|
|
11905
|
+
const entries = (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true });
|
|
11838
11906
|
for (const entry of entries) {
|
|
11839
11907
|
const fullPath = (0, import_node_path6.join)(dir, entry.name);
|
|
11840
11908
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -11853,14 +11921,14 @@ function discoverPlans() {
|
|
|
11853
11921
|
const candidates = [];
|
|
11854
11922
|
const seen = /* @__PURE__ */ new Set();
|
|
11855
11923
|
for (const plansDir of [localPlansDir, homePlansDir]) {
|
|
11856
|
-
if (!(0,
|
|
11924
|
+
if (!(0, import_node_fs8.existsSync)(plansDir)) continue;
|
|
11857
11925
|
try {
|
|
11858
|
-
for (const f of (0,
|
|
11926
|
+
for (const f of (0, import_node_fs8.readdirSync)(plansDir)) {
|
|
11859
11927
|
if (!f.endsWith(".md") || seen.has(f)) continue;
|
|
11860
11928
|
seen.add(f);
|
|
11861
11929
|
const fullPath = (0, import_node_path6.join)(plansDir, f);
|
|
11862
11930
|
try {
|
|
11863
|
-
const stat = (0,
|
|
11931
|
+
const stat = (0, import_node_fs8.statSync)(fullPath);
|
|
11864
11932
|
candidates.push({ name: f, path: fullPath, mtime: stat.mtimeMs, size: stat.size });
|
|
11865
11933
|
} catch {
|
|
11866
11934
|
}
|
|
@@ -11873,7 +11941,7 @@ function discoverPlans() {
|
|
|
11873
11941
|
for (const entry of candidates.slice(0, MAX_PLAN_FILES)) {
|
|
11874
11942
|
if (entry.size > MAX_PLAN_FILE_BYTES) continue;
|
|
11875
11943
|
try {
|
|
11876
|
-
const content = (0,
|
|
11944
|
+
const content = (0, import_node_fs8.readFileSync)(entry.path, "utf-8");
|
|
11877
11945
|
result.push({ name: entry.name, content });
|
|
11878
11946
|
} catch {
|
|
11879
11947
|
}
|
|
@@ -11882,19 +11950,19 @@ function discoverPlans() {
|
|
|
11882
11950
|
}
|
|
11883
11951
|
|
|
11884
11952
|
// src/lib/snapshot.ts
|
|
11885
|
-
var
|
|
11953
|
+
var import_node_fs9 = require("node:fs");
|
|
11886
11954
|
var import_node_path7 = require("node:path");
|
|
11887
11955
|
var import_node_child_process7 = require("node:child_process");
|
|
11888
11956
|
function generateSnapshotDiffs(files) {
|
|
11889
|
-
if (!(0,
|
|
11957
|
+
if (!(0, import_node_fs9.existsSync)(SNAPSHOT_DIR)) {
|
|
11890
11958
|
return { diffs: [], has_snapshots: false };
|
|
11891
11959
|
}
|
|
11892
11960
|
const diffs = [];
|
|
11893
11961
|
for (const file of files) {
|
|
11894
11962
|
const snapshotPath = (0, import_node_path7.join)(SNAPSHOT_DIR, file.path);
|
|
11895
11963
|
const language = file.language ?? detectLanguage(file.path);
|
|
11896
|
-
if ((0,
|
|
11897
|
-
const oldContent = (0,
|
|
11964
|
+
if ((0, import_node_fs9.existsSync)(snapshotPath)) {
|
|
11965
|
+
const oldContent = (0, import_node_fs9.readFileSync)(snapshotPath, "utf-8");
|
|
11898
11966
|
if (oldContent === file.content) continue;
|
|
11899
11967
|
const diff = computeDiff(oldContent, file.content, file.path);
|
|
11900
11968
|
if (diff) {
|
|
@@ -11920,8 +11988,8 @@ function saveSnapshots(files) {
|
|
|
11920
11988
|
for (const file of files) {
|
|
11921
11989
|
const snapshotPath = (0, import_node_path7.join)(SNAPSHOT_DIR, file.path);
|
|
11922
11990
|
snapshotPaths.add(snapshotPath);
|
|
11923
|
-
(0,
|
|
11924
|
-
(0,
|
|
11991
|
+
(0, import_node_fs9.mkdirSync)((0, import_node_path7.dirname)(snapshotPath), { recursive: true });
|
|
11992
|
+
(0, import_node_fs9.writeFileSync)(snapshotPath, file.content);
|
|
11925
11993
|
}
|
|
11926
11994
|
cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
|
|
11927
11995
|
}
|
|
@@ -11929,9 +11997,9 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
11929
11997
|
const tmpOld = (0, import_node_path7.join)(SNAPSHOT_DIR, ".diff-old.tmp");
|
|
11930
11998
|
const tmpNew = (0, import_node_path7.join)(SNAPSHOT_DIR, ".diff-new.tmp");
|
|
11931
11999
|
try {
|
|
11932
|
-
(0,
|
|
11933
|
-
(0,
|
|
11934
|
-
(0,
|
|
12000
|
+
(0, import_node_fs9.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
|
|
12001
|
+
(0, import_node_fs9.writeFileSync)(tmpOld, oldContent);
|
|
12002
|
+
(0, import_node_fs9.writeFileSync)(tmpNew, newContent);
|
|
11935
12003
|
const result = (0, import_node_child_process7.execSync)(
|
|
11936
12004
|
`git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
|
|
11937
12005
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -11945,32 +12013,32 @@ function computeDiff(oldContent, newContent, filePath) {
|
|
|
11945
12013
|
return null;
|
|
11946
12014
|
} finally {
|
|
11947
12015
|
try {
|
|
11948
|
-
(0,
|
|
12016
|
+
(0, import_node_fs9.unlinkSync)(tmpOld);
|
|
11949
12017
|
} catch {
|
|
11950
12018
|
}
|
|
11951
12019
|
try {
|
|
11952
|
-
(0,
|
|
12020
|
+
(0, import_node_fs9.unlinkSync)(tmpNew);
|
|
11953
12021
|
} catch {
|
|
11954
12022
|
}
|
|
11955
12023
|
}
|
|
11956
12024
|
}
|
|
11957
12025
|
function cleanStaleSnapshots(dir, keepSet) {
|
|
11958
|
-
if (!(0,
|
|
12026
|
+
if (!(0, import_node_fs9.existsSync)(dir)) return;
|
|
11959
12027
|
try {
|
|
11960
|
-
const entries = (0,
|
|
12028
|
+
const entries = (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true });
|
|
11961
12029
|
for (const entry of entries) {
|
|
11962
12030
|
if (entry.name.startsWith(".")) continue;
|
|
11963
12031
|
const fullPath = (0, import_node_path7.join)(dir, entry.name);
|
|
11964
12032
|
if (entry.isDirectory()) {
|
|
11965
12033
|
cleanStaleSnapshots(fullPath, keepSet);
|
|
11966
12034
|
try {
|
|
11967
|
-
const remaining = (0,
|
|
11968
|
-
if (remaining.length === 0) (0,
|
|
12035
|
+
const remaining = (0, import_node_fs9.readdirSync)(fullPath);
|
|
12036
|
+
if (remaining.length === 0) (0, import_node_fs9.rmdirSync)(fullPath);
|
|
11969
12037
|
} catch {
|
|
11970
12038
|
}
|
|
11971
12039
|
} else if (!keepSet.has(fullPath)) {
|
|
11972
12040
|
try {
|
|
11973
|
-
(0,
|
|
12041
|
+
(0, import_node_fs9.unlinkSync)(fullPath);
|
|
11974
12042
|
} catch {
|
|
11975
12043
|
}
|
|
11976
12044
|
}
|
|
@@ -11980,14 +12048,14 @@ function cleanStaleSnapshots(dir, keepSet) {
|
|
|
11980
12048
|
}
|
|
11981
12049
|
|
|
11982
12050
|
// src/lib/offline.ts
|
|
11983
|
-
var
|
|
12051
|
+
var import_node_fs10 = require("node:fs");
|
|
11984
12052
|
var import_node_crypto2 = require("node:crypto");
|
|
11985
12053
|
function cacheRequest(body) {
|
|
11986
12054
|
try {
|
|
11987
|
-
(0,
|
|
12055
|
+
(0, import_node_fs10.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
11988
12056
|
const suffix = (0, import_node_crypto2.randomBytes)(4).toString("hex");
|
|
11989
12057
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
11990
|
-
(0,
|
|
12058
|
+
(0, import_node_fs10.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(body));
|
|
11991
12059
|
} catch {
|
|
11992
12060
|
}
|
|
11993
12061
|
}
|
|
@@ -12053,11 +12121,12 @@ function isGitOnlyPrompt(prompt) {
|
|
|
12053
12121
|
if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
|
|
12054
12122
|
return true;
|
|
12055
12123
|
}
|
|
12056
|
-
function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts) {
|
|
12124
|
+
function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary) {
|
|
12125
|
+
const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0));
|
|
12057
12126
|
if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
|
|
12058
|
-
return "skip";
|
|
12127
|
+
if (!agentAuthoredCode) return "skip";
|
|
12059
12128
|
}
|
|
12060
|
-
if (noFilesChanged && !!assistantResponse) {
|
|
12129
|
+
if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
|
|
12061
12130
|
return "plan";
|
|
12062
12131
|
}
|
|
12063
12132
|
for (const prompt of conversationPrompts) {
|
|
@@ -12069,7 +12138,7 @@ function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPromp
|
|
|
12069
12138
|
}
|
|
12070
12139
|
|
|
12071
12140
|
// src/lib/transcript.ts
|
|
12072
|
-
var
|
|
12141
|
+
var import_node_fs11 = require("node:fs");
|
|
12073
12142
|
var MAX_READ_BYTES = 256 * 1024;
|
|
12074
12143
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
12075
12144
|
var MAX_FILES_LIST = 20;
|
|
@@ -12091,14 +12160,14 @@ async function extractActionSummary(transcriptPath) {
|
|
|
12091
12160
|
function readTurnLines(transcriptPath) {
|
|
12092
12161
|
let size;
|
|
12093
12162
|
try {
|
|
12094
|
-
size = (0,
|
|
12163
|
+
size = (0, import_node_fs11.statSync)(transcriptPath).size;
|
|
12095
12164
|
} catch {
|
|
12096
12165
|
return null;
|
|
12097
12166
|
}
|
|
12098
12167
|
if (size === 0) return null;
|
|
12099
12168
|
let raw;
|
|
12100
12169
|
if (size <= SMALL_FILE_BYTES) {
|
|
12101
|
-
raw = (0,
|
|
12170
|
+
raw = (0, import_node_fs11.readFileSync)(transcriptPath, "utf-8");
|
|
12102
12171
|
} else {
|
|
12103
12172
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
12104
12173
|
const fd = require("node:fs").openSync(transcriptPath, "r");
|
|
@@ -12319,7 +12388,7 @@ async function runAnalyze(opts, globals) {
|
|
|
12319
12388
|
const specs = discoverSpecs();
|
|
12320
12389
|
const plans = discoverPlans();
|
|
12321
12390
|
const conversationPrompts = (conversation?.prompts ?? []).map((p) => p.prompt);
|
|
12322
|
-
let analysisMode = detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts);
|
|
12391
|
+
let analysisMode = detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary);
|
|
12323
12392
|
if (analysisMode === "skip") {
|
|
12324
12393
|
passAndExit("Git operation only \u2014 no code authored to analyze");
|
|
12325
12394
|
}
|
|
@@ -12462,19 +12531,44 @@ async function runAnalyze(opts, globals) {
|
|
|
12462
12531
|
}
|
|
12463
12532
|
requestBody.intent_context = intentContext;
|
|
12464
12533
|
}
|
|
12465
|
-
const
|
|
12534
|
+
const ANALYZE_TIMEOUT_MS = 1e5;
|
|
12535
|
+
let result = await apiRequest({
|
|
12466
12536
|
method: "POST",
|
|
12467
12537
|
path: "/analyze",
|
|
12468
12538
|
serviceUrl: urlResult.data,
|
|
12469
12539
|
token: tokenResult.data.token,
|
|
12470
12540
|
body: requestBody,
|
|
12471
12541
|
verbose: globals.verbose,
|
|
12472
|
-
timeout:
|
|
12542
|
+
timeout: ANALYZE_TIMEOUT_MS,
|
|
12543
|
+
cmd: "analyze"
|
|
12473
12544
|
});
|
|
12545
|
+
if (!result.ok && (result.category === "network" || result.category === "timeout")) {
|
|
12546
|
+
logEvent("analyze_warm_retry", { first_error: result.error, category: result.category });
|
|
12547
|
+
await apiRequest({
|
|
12548
|
+
method: "GET",
|
|
12549
|
+
path: "/memory",
|
|
12550
|
+
serviceUrl: urlResult.data,
|
|
12551
|
+
token: tokenResult.data.token,
|
|
12552
|
+
verbose: globals.verbose,
|
|
12553
|
+
timeout: 15e3,
|
|
12554
|
+
cmd: "analyze_warmup"
|
|
12555
|
+
});
|
|
12556
|
+
result = await apiRequest({
|
|
12557
|
+
method: "POST",
|
|
12558
|
+
path: "/analyze",
|
|
12559
|
+
serviceUrl: urlResult.data,
|
|
12560
|
+
token: tokenResult.data.token,
|
|
12561
|
+
body: requestBody,
|
|
12562
|
+
verbose: globals.verbose,
|
|
12563
|
+
timeout: ANALYZE_TIMEOUT_MS,
|
|
12564
|
+
cmd: "analyze",
|
|
12565
|
+
retry: true
|
|
12566
|
+
});
|
|
12567
|
+
}
|
|
12474
12568
|
if (!result.ok) {
|
|
12475
12569
|
cacheRequest(requestBody);
|
|
12476
12570
|
const fallback = buildOfflineFallback(
|
|
12477
|
-
`GATE.md
|
|
12571
|
+
`GATE.md offline \u2014 ${result.error}`,
|
|
12478
12572
|
staticResults
|
|
12479
12573
|
);
|
|
12480
12574
|
printJsonCompact(fallback);
|
|
@@ -12586,7 +12680,7 @@ async function runAnalyze(opts, globals) {
|
|
|
12586
12680
|
}
|
|
12587
12681
|
|
|
12588
12682
|
// src/commands/review.ts
|
|
12589
|
-
var
|
|
12683
|
+
var import_node_fs12 = require("node:fs");
|
|
12590
12684
|
function registerReviewCommand(program2) {
|
|
12591
12685
|
program2.command("review").description("Run on-demand GATE.md analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars)").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
|
|
12592
12686
|
const globals = program2.opts();
|
|
@@ -12605,7 +12699,7 @@ async function runReview(opts, globals) {
|
|
|
12605
12699
|
const securityFiles = filterSecurity(allFiles);
|
|
12606
12700
|
let staticResults;
|
|
12607
12701
|
if (isCodacyAvailable()) {
|
|
12608
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
12702
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs12.existsSync)(f) || resolveFile(f) !== null);
|
|
12609
12703
|
staticResults = runCodacyAnalysis(scannable);
|
|
12610
12704
|
} else {
|
|
12611
12705
|
staticResults = {
|
|
@@ -12630,7 +12724,7 @@ async function runReview(opts, globals) {
|
|
|
12630
12724
|
const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
|
|
12631
12725
|
specs = [];
|
|
12632
12726
|
for (const p of specPaths) {
|
|
12633
|
-
if (!(0,
|
|
12727
|
+
if (!(0, import_node_fs12.existsSync)(p)) continue;
|
|
12634
12728
|
try {
|
|
12635
12729
|
const { readFileSync: readFileSync6 } = await import("node:fs");
|
|
12636
12730
|
const content = readFileSync6(p, "utf-8");
|
|
@@ -12691,7 +12785,7 @@ async function runReview(opts, globals) {
|
|
|
12691
12785
|
}
|
|
12692
12786
|
|
|
12693
12787
|
// src/commands/init.ts
|
|
12694
|
-
var
|
|
12788
|
+
var import_node_fs13 = require("node:fs");
|
|
12695
12789
|
var import_promises8 = require("node:fs/promises");
|
|
12696
12790
|
var import_node_path8 = require("node:path");
|
|
12697
12791
|
var import_node_child_process8 = require("node:child_process");
|
|
@@ -12705,7 +12799,7 @@ function resolveDataDir() {
|
|
|
12705
12799
|
// local dev: running from repo root
|
|
12706
12800
|
];
|
|
12707
12801
|
for (const candidate of candidates) {
|
|
12708
|
-
if ((0,
|
|
12802
|
+
if ((0, import_node_fs13.existsSync)((0, import_node_path8.join)(candidate, "skills"))) {
|
|
12709
12803
|
return candidate;
|
|
12710
12804
|
}
|
|
12711
12805
|
}
|
|
@@ -12721,7 +12815,7 @@ function registerInitCommand(program2) {
|
|
|
12721
12815
|
program2.command("init").description("Initialize GATE.md in the current project").option("--force", "Overwrite existing skills and hooks").action(async (opts) => {
|
|
12722
12816
|
const force = opts.force ?? false;
|
|
12723
12817
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
12724
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
12818
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs13.existsSync)(m));
|
|
12725
12819
|
if (!isProject) {
|
|
12726
12820
|
printError("No project detected in the current directory.");
|
|
12727
12821
|
printInfo('Run "gate init" from your project root.');
|
|
@@ -12781,14 +12875,14 @@ function registerInitCommand(program2) {
|
|
|
12781
12875
|
for (const skill of skills) {
|
|
12782
12876
|
const src = (0, import_node_path8.join)(skillsSource, skill);
|
|
12783
12877
|
const dest = (0, import_node_path8.join)(skillsDest, skill);
|
|
12784
|
-
if (!(0,
|
|
12878
|
+
if (!(0, import_node_fs13.existsSync)(src)) {
|
|
12785
12879
|
printWarn(` Skill data not found: ${skill}`);
|
|
12786
12880
|
continue;
|
|
12787
12881
|
}
|
|
12788
|
-
if ((0,
|
|
12882
|
+
if ((0, import_node_fs13.existsSync)(dest) && !force) {
|
|
12789
12883
|
const srcSkill = (0, import_node_path8.join)(src, "SKILL.md");
|
|
12790
12884
|
const destSkill = (0, import_node_path8.join)(dest, "SKILL.md");
|
|
12791
|
-
if ((0,
|
|
12885
|
+
if ((0, import_node_fs13.existsSync)(destSkill)) {
|
|
12792
12886
|
try {
|
|
12793
12887
|
const srcContent = await (0, import_promises8.readFile)(srcSkill, "utf-8");
|
|
12794
12888
|
const destContent = await (0, import_promises8.readFile)(destSkill, "utf-8");
|
|
@@ -12834,7 +12928,7 @@ function registerInitCommand(program2) {
|
|
|
12834
12928
|
}
|
|
12835
12929
|
|
|
12836
12930
|
// src/cli.ts
|
|
12837
|
-
program.name("gate").description("CLI for GATE.md quality gate service").version("0.14.
|
|
12931
|
+
program.name("gate").description("CLI for GATE.md quality gate service").version("0.14.2").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
12838
12932
|
registerAuthCommands(program);
|
|
12839
12933
|
registerHooksCommands(program);
|
|
12840
12934
|
registerIntentCommands(program);
|