@codacy/gate-cli 0.5.0 → 0.7.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.
Files changed (2) hide show
  1. package/bin/gate.js +302 -110
  2. package/package.json +2 -2
package/bin/gate.js CHANGED
@@ -10373,6 +10373,10 @@ var MAX_TOTAL_SPEC_BYTES = 30720;
10373
10373
  var MAX_PLAN_FILES = 3;
10374
10374
  var MAX_PLAN_FILE_BYTES = 10240;
10375
10375
  var MAX_INTENT_CHARS = 2e3;
10376
+ var SNAPSHOT_DIR = `${GATE_DIR}/.snapshot`;
10377
+ var CONVERSATION_BUFFER_FILE = `${GATE_DIR}/.conversation-buffer`;
10378
+ var CONVERSATION_MAX_ENTRIES = 10;
10379
+ var CONVERSATION_WINDOW_MINUTES = 15;
10376
10380
  var MAX_FINDINGS = 25;
10377
10381
  var ANALYZABLE_EXTENSIONS = /* @__PURE__ */ new Set([
10378
10382
  "ts",
@@ -10852,41 +10856,113 @@ function registerHooksCommands(program2) {
10852
10856
  });
10853
10857
  }
10854
10858
 
10855
- // src/lib/intent.ts
10859
+ // src/lib/conversation-buffer.ts
10856
10860
  var import_promises5 = require("node:fs/promises");
10857
- async function writeIntent(prompt, sessionId) {
10861
+ var import_node_fs = require("node:fs");
10862
+ var import_node_child_process4 = require("node:child_process");
10863
+ function stripImageReferences(text) {
10864
+ return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
10865
+ }
10866
+ async function appendToConversationBuffer(prompt, sessionId) {
10858
10867
  try {
10859
10868
  await (0, import_promises5.mkdir)(GATE_DIR, { recursive: true });
10860
- const truncated = prompt.length > MAX_INTENT_CHARS ? prompt.slice(0, MAX_INTENT_CHARS) : prompt;
10861
- const data = {
10862
- prompt: truncated,
10869
+ let sanitized = prompt.length > MAX_INTENT_CHARS ? prompt.slice(0, MAX_INTENT_CHARS) : prompt;
10870
+ sanitized = stripImageReferences(sanitized);
10871
+ const entry = {
10872
+ prompt: sanitized,
10863
10873
  session_id: sessionId,
10864
10874
  captured_at: (/* @__PURE__ */ new Date()).toISOString()
10865
10875
  };
10866
- const tmpFile = `${INTENT_FILE}.tmp`;
10867
- await (0, import_promises5.writeFile)(tmpFile, JSON.stringify(data) + "\n");
10868
- await (0, import_promises5.rename)(tmpFile, INTENT_FILE);
10876
+ const entries = await readBufferEntries();
10877
+ const cutoff = Date.now() - CONVERSATION_WINDOW_MINUTES * 60 * 1e3;
10878
+ const recent = entries.filter((e) => {
10879
+ const ts = new Date(e.captured_at).getTime();
10880
+ return !isNaN(ts) && ts > cutoff;
10881
+ });
10882
+ recent.push(entry);
10883
+ const capped = recent.slice(-CONVERSATION_MAX_ENTRIES);
10884
+ const content = capped.map((e) => JSON.stringify(e)).join("\n") + "\n";
10885
+ const tmpFile = `${CONVERSATION_BUFFER_FILE}.tmp`;
10886
+ await (0, import_promises5.writeFile)(tmpFile, content);
10887
+ await (0, import_promises5.rename)(tmpFile, CONVERSATION_BUFFER_FILE);
10869
10888
  } catch {
10870
10889
  }
10871
10890
  }
10872
- async function readAndClearIntent() {
10891
+ async function readAndClearConversationBuffer() {
10873
10892
  try {
10874
- const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
10875
- await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
10876
- });
10877
- return JSON.parse(content);
10893
+ if ((0, import_node_fs.existsSync)(CONVERSATION_BUFFER_FILE)) {
10894
+ const entries = await readBufferEntries();
10895
+ await (0, import_promises5.unlink)(CONVERSATION_BUFFER_FILE).catch(() => {
10896
+ });
10897
+ if (entries.length > 0) {
10898
+ return {
10899
+ prompts: entries,
10900
+ recent_commits: getRecentCommitMessages()
10901
+ };
10902
+ }
10903
+ }
10904
+ if ((0, import_node_fs.existsSync)(INTENT_FILE)) {
10905
+ try {
10906
+ const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
10907
+ await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
10908
+ });
10909
+ const data = JSON.parse(content);
10910
+ if (data.prompt) {
10911
+ return {
10912
+ prompts: [{
10913
+ prompt: stripImageReferences(data.prompt),
10914
+ session_id: data.session_id ?? "",
10915
+ captured_at: data.captured_at ?? (/* @__PURE__ */ new Date()).toISOString()
10916
+ }],
10917
+ recent_commits: getRecentCommitMessages()
10918
+ };
10919
+ }
10920
+ } catch {
10921
+ }
10922
+ }
10923
+ return null;
10878
10924
  } catch {
10879
10925
  return null;
10880
10926
  }
10881
10927
  }
10928
+ async function readBufferEntries() {
10929
+ try {
10930
+ const content = await (0, import_promises5.readFile)(CONVERSATION_BUFFER_FILE, "utf-8");
10931
+ const entries = [];
10932
+ for (const line of content.split("\n")) {
10933
+ const trimmed = line.trim();
10934
+ if (!trimmed) continue;
10935
+ try {
10936
+ const parsed = JSON.parse(trimmed);
10937
+ if (parsed.prompt) entries.push(parsed);
10938
+ } catch {
10939
+ }
10940
+ }
10941
+ return entries;
10942
+ } catch {
10943
+ return [];
10944
+ }
10945
+ }
10946
+ function getRecentCommitMessages() {
10947
+ try {
10948
+ const output = (0, import_node_child_process4.execSync)(
10949
+ 'git log --since="30 minutes ago" --format="%s" -5',
10950
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
10951
+ ).trim();
10952
+ if (!output) return [];
10953
+ return output.split("\n").filter((l) => l.length > 0);
10954
+ } catch {
10955
+ return [];
10956
+ }
10957
+ }
10882
10958
 
10883
10959
  // src/commands/intent.ts
10884
- var import_node_fs = require("node:fs");
10960
+ var import_node_fs2 = require("node:fs");
10885
10961
  function registerIntentCommands(program2) {
10886
10962
  const intent = program2.command("intent").description("Manage intent capture");
10887
10963
  intent.command("capture").description("Capture user intent from stdin (used by UserPromptSubmit hook)").action(async () => {
10888
10964
  try {
10889
- if (!(0, import_node_fs.existsSync)(GATE_DIR)) {
10965
+ if (!(0, import_node_fs2.existsSync)(GATE_DIR)) {
10890
10966
  process.exit(0);
10891
10967
  }
10892
10968
  const chunks = [];
@@ -10907,7 +10983,7 @@ function registerIntentCommands(program2) {
10907
10983
  if (!prompt) {
10908
10984
  process.exit(0);
10909
10985
  }
10910
- await writeIntent(prompt, event.session_id ?? "");
10986
+ await appendToConversationBuffer(prompt, event.session_id ?? "");
10911
10987
  } catch {
10912
10988
  }
10913
10989
  process.exit(0);
@@ -11224,18 +11300,18 @@ function registerFeedbackCommand(program2) {
11224
11300
  }
11225
11301
 
11226
11302
  // src/lib/git.ts
11227
- var import_node_child_process4 = require("node:child_process");
11228
- var import_node_fs2 = require("node:fs");
11303
+ var import_node_child_process5 = require("node:child_process");
11304
+ var import_node_fs3 = require("node:fs");
11229
11305
  var import_node_path4 = require("node:path");
11230
11306
  function resolveFile(relpath) {
11231
- if ((0, import_node_fs2.existsSync)(relpath)) return relpath;
11232
- if ((0, import_node_fs2.existsSync)(".claude/worktrees")) {
11307
+ if ((0, import_node_fs3.existsSync)(relpath)) return relpath;
11308
+ if ((0, import_node_fs3.existsSync)(".claude/worktrees")) {
11233
11309
  try {
11234
- const entries = (0, import_node_fs2.readdirSync)(".claude/worktrees", { withFileTypes: true });
11310
+ const entries = (0, import_node_fs3.readdirSync)(".claude/worktrees", { withFileTypes: true });
11235
11311
  for (const entry of entries) {
11236
11312
  if (!entry.isDirectory()) continue;
11237
11313
  const candidate = (0, import_node_path4.join)(".claude/worktrees", entry.name, relpath);
11238
- if ((0, import_node_fs2.existsSync)(candidate)) return candidate;
11314
+ if ((0, import_node_fs3.existsSync)(candidate)) return candidate;
11239
11315
  }
11240
11316
  } catch {
11241
11317
  }
@@ -11244,7 +11320,7 @@ function resolveFile(relpath) {
11244
11320
  }
11245
11321
  function execGit(cmd) {
11246
11322
  try {
11247
- return (0, import_node_child_process4.execSync)(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
11323
+ return (0, import_node_child_process5.execSync)(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
11248
11324
  } catch {
11249
11325
  return "";
11250
11326
  }
@@ -11254,6 +11330,7 @@ function splitLines(s) {
11254
11330
  }
11255
11331
  function getChangedFiles() {
11256
11332
  const sets = /* @__PURE__ */ new Set();
11333
+ let hasRecentCommitFiles = false;
11257
11334
  for (const f of splitLines(execGit("git diff --name-only HEAD"))) {
11258
11335
  sets.add(f);
11259
11336
  }
@@ -11269,22 +11346,26 @@ function getChangedFiles() {
11269
11346
  const hasUnstaged = splitLines(execGit("git diff --name-only HEAD")).length > 0;
11270
11347
  const hasStaged = splitLines(execGit("git diff --name-only --cached")).length > 0;
11271
11348
  if (commitAge < 120 && !hasUnstaged && !hasStaged) {
11272
- for (const f of splitLines(execGit("git diff --name-only HEAD~1..HEAD"))) {
11273
- sets.add(f);
11349
+ const recentFiles = splitLines(execGit("git diff --name-only HEAD~1..HEAD"));
11350
+ if (recentFiles.length > 0) {
11351
+ hasRecentCommitFiles = true;
11352
+ for (const f of recentFiles) {
11353
+ sets.add(f);
11354
+ }
11274
11355
  }
11275
11356
  }
11276
11357
  for (const f of getWorktreeFiles()) {
11277
11358
  sets.add(f);
11278
11359
  }
11279
- return Array.from(sets);
11360
+ return { files: Array.from(sets), hasRecentCommitFiles };
11280
11361
  }
11281
11362
  function getWorktreeFiles() {
11282
11363
  const result = [];
11283
11364
  const worktreeDir = ".claude/worktrees";
11284
- if (!(0, import_node_fs2.existsSync)(worktreeDir)) return result;
11365
+ if (!(0, import_node_fs3.existsSync)(worktreeDir)) return result;
11285
11366
  try {
11286
11367
  const fiveMinAgo = Date.now() - 5 * 60 * 1e3;
11287
- const entries = (0, import_node_fs2.readdirSync)(worktreeDir, { withFileTypes: true });
11368
+ const entries = (0, import_node_fs3.readdirSync)(worktreeDir, { withFileTypes: true });
11288
11369
  for (const entry of entries) {
11289
11370
  if (!entry.isDirectory()) continue;
11290
11371
  const wtDir = (0, import_node_path4.join)(worktreeDir, entry.name);
@@ -11296,7 +11377,7 @@ function getWorktreeFiles() {
11296
11377
  }
11297
11378
  function scanDir(baseDir, dir, minMtime, result) {
11298
11379
  try {
11299
- const entries = (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true });
11380
+ const entries = (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true });
11300
11381
  for (const entry of entries) {
11301
11382
  const fullPath = (0, import_node_path4.join)(dir, entry.name);
11302
11383
  if (entry.isDirectory()) {
@@ -11306,7 +11387,7 @@ function scanDir(baseDir, dir, minMtime, result) {
11306
11387
  const ext = (0, import_node_path4.extname)(entry.name).slice(1);
11307
11388
  if (!ANALYZABLE_EXTENSIONS.has(ext)) continue;
11308
11389
  try {
11309
- const stat = (0, import_node_fs2.statSync)(fullPath);
11390
+ const stat = (0, import_node_fs3.statSync)(fullPath);
11310
11391
  if (stat.mtimeMs >= minMtime) {
11311
11392
  const relPath = fullPath.slice(baseDir.length + 1);
11312
11393
  result.push(relPath);
@@ -11345,7 +11426,7 @@ function getCurrentCommit() {
11345
11426
  }
11346
11427
 
11347
11428
  // src/lib/files.ts
11348
- var import_node_fs3 = require("node:fs");
11429
+ var import_node_fs4 = require("node:fs");
11349
11430
  var import_node_path5 = require("node:path");
11350
11431
  var LANG_MAP = {
11351
11432
  // Analyzable (static analysis + Gemini)
@@ -11422,7 +11503,7 @@ function sortByMtime(files) {
11422
11503
  const resolved = resolveFile(f);
11423
11504
  if (!resolved) return null;
11424
11505
  try {
11425
- const stat = (0, import_node_fs3.statSync)(resolved);
11506
+ const stat = (0, import_node_fs4.statSync)(resolved);
11426
11507
  return { path: f, resolved, mtime: stat.mtimeMs };
11427
11508
  } catch {
11428
11509
  return null;
@@ -11444,7 +11525,7 @@ function collectCodeDelta(files, opts) {
11444
11525
  if (!resolved) continue;
11445
11526
  let size;
11446
11527
  try {
11447
- size = (0, import_node_fs3.statSync)(resolved).size;
11528
+ size = (0, import_node_fs4.statSync)(resolved).size;
11448
11529
  } catch {
11449
11530
  continue;
11450
11531
  }
@@ -11452,7 +11533,7 @@ function collectCodeDelta(files, opts) {
11452
11533
  if (totalSize + size > maxTotalBytes) break;
11453
11534
  let content;
11454
11535
  try {
11455
- content = (0, import_node_fs3.readFileSync)(resolved, "utf-8");
11536
+ content = (0, import_node_fs4.readFileSync)(resolved, "utf-8");
11456
11537
  } catch {
11457
11538
  continue;
11458
11539
  }
@@ -11475,12 +11556,12 @@ function collectCodeDelta(files, opts) {
11475
11556
  }
11476
11557
 
11477
11558
  // src/lib/debounce.ts
11478
- var import_node_fs4 = require("node:fs");
11559
+ var import_node_fs5 = require("node:fs");
11479
11560
  var import_node_crypto = require("node:crypto");
11480
11561
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS) {
11481
- if (!(0, import_node_fs4.existsSync)(DEBOUNCE_FILE)) return null;
11562
+ if (!(0, import_node_fs5.existsSync)(DEBOUNCE_FILE)) return null;
11482
11563
  try {
11483
- const lastTs = parseInt((0, import_node_fs4.readFileSync)(DEBOUNCE_FILE, "utf-8").trim(), 10);
11564
+ const lastTs = parseInt((0, import_node_fs5.readFileSync)(DEBOUNCE_FILE, "utf-8").trim(), 10);
11484
11565
  const nowTs = Math.floor(Date.now() / 1e3);
11485
11566
  const elapsed = nowTs - lastTs;
11486
11567
  if (elapsed < debounceSeconds) {
@@ -11490,11 +11571,12 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS) {
11490
11571
  }
11491
11572
  return null;
11492
11573
  }
11493
- function checkMtime(files) {
11494
- if (!(0, import_node_fs4.existsSync)(DEBOUNCE_FILE)) return null;
11574
+ function checkMtime(files, bypassForRecentCommits) {
11575
+ if (bypassForRecentCommits) return null;
11576
+ if (!(0, import_node_fs5.existsSync)(DEBOUNCE_FILE)) return null;
11495
11577
  let debounceTime;
11496
11578
  try {
11497
- debounceTime = (0, import_node_fs4.statSync)(DEBOUNCE_FILE).mtimeMs;
11579
+ debounceTime = (0, import_node_fs5.statSync)(DEBOUNCE_FILE).mtimeMs;
11498
11580
  } catch {
11499
11581
  return null;
11500
11582
  }
@@ -11502,7 +11584,7 @@ function checkMtime(files) {
11502
11584
  const resolved = resolveFile(f);
11503
11585
  if (!resolved) continue;
11504
11586
  try {
11505
- const stat = (0, import_node_fs4.statSync)(resolved);
11587
+ const stat = (0, import_node_fs5.statSync)(resolved);
11506
11588
  if (stat.mtimeMs > debounceTime) {
11507
11589
  return null;
11508
11590
  }
@@ -11518,8 +11600,8 @@ function computeContentHash(files) {
11518
11600
  for (const f of sorted) {
11519
11601
  const resolved = resolveFile(f) ?? f;
11520
11602
  try {
11521
- if ((0, import_node_fs4.existsSync)(resolved)) {
11522
- hash.update((0, import_node_fs4.readFileSync)(resolved));
11603
+ if ((0, import_node_fs5.existsSync)(resolved)) {
11604
+ hash.update((0, import_node_fs5.readFileSync)(resolved));
11523
11605
  }
11524
11606
  } catch {
11525
11607
  }
@@ -11528,9 +11610,9 @@ function computeContentHash(files) {
11528
11610
  }
11529
11611
  function checkContentHash(files) {
11530
11612
  const hash = computeContentHash(files);
11531
- if ((0, import_node_fs4.existsSync)(HASH_FILE)) {
11613
+ if ((0, import_node_fs5.existsSync)(HASH_FILE)) {
11532
11614
  try {
11533
- const storedHash = (0, import_node_fs4.readFileSync)(HASH_FILE, "utf-8").trim();
11615
+ const storedHash = (0, import_node_fs5.readFileSync)(HASH_FILE, "utf-8").trim();
11534
11616
  if (hash === storedHash) {
11535
11617
  return { skip: "No source changes since last analysis", hash };
11536
11618
  }
@@ -11540,23 +11622,23 @@ function checkContentHash(files) {
11540
11622
  return { skip: null, hash };
11541
11623
  }
11542
11624
  function recordAnalysisStart() {
11543
- (0, import_node_fs4.mkdirSync)(GATE_DIR, { recursive: true });
11544
- (0, import_node_fs4.writeFileSync)(DEBOUNCE_FILE, String(Math.floor(Date.now() / 1e3)));
11625
+ (0, import_node_fs5.mkdirSync)(GATE_DIR, { recursive: true });
11626
+ (0, import_node_fs5.writeFileSync)(DEBOUNCE_FILE, String(Math.floor(Date.now() / 1e3)));
11545
11627
  }
11546
11628
  function recordPassHash(hash) {
11547
- (0, import_node_fs4.writeFileSync)(HASH_FILE, hash);
11629
+ (0, import_node_fs5.writeFileSync)(HASH_FILE, hash);
11548
11630
  }
11549
11631
  function narrowToRecent(files) {
11550
- if (!(0, import_node_fs4.existsSync)(DEBOUNCE_FILE)) return files;
11632
+ if (!(0, import_node_fs5.existsSync)(DEBOUNCE_FILE)) return files;
11551
11633
  let debounceTime;
11552
11634
  try {
11553
- debounceTime = (0, import_node_fs4.statSync)(DEBOUNCE_FILE).mtimeMs;
11635
+ debounceTime = (0, import_node_fs5.statSync)(DEBOUNCE_FILE).mtimeMs;
11554
11636
  } catch {
11555
11637
  return files;
11556
11638
  }
11557
11639
  const recent = files.filter((f) => {
11558
11640
  try {
11559
- return (0, import_node_fs4.existsSync)(f) && (0, import_node_fs4.statSync)(f).mtimeMs > debounceTime;
11641
+ return (0, import_node_fs5.existsSync)(f) && (0, import_node_fs5.statSync)(f).mtimeMs > debounceTime;
11560
11642
  } catch {
11561
11643
  return false;
11562
11644
  }
@@ -11564,9 +11646,9 @@ function narrowToRecent(files) {
11564
11646
  return recent.length > 0 ? recent : files;
11565
11647
  }
11566
11648
  function readIteration(currentCommit, contentHash) {
11567
- if (!(0, import_node_fs4.existsSync)(ITERATION_FILE)) return 1;
11649
+ if (!(0, import_node_fs5.existsSync)(ITERATION_FILE)) return 1;
11568
11650
  try {
11569
- const stored = (0, import_node_fs4.readFileSync)(ITERATION_FILE, "utf-8").trim();
11651
+ const stored = (0, import_node_fs5.readFileSync)(ITERATION_FILE, "utf-8").trim();
11570
11652
  const parts = stored.split(":");
11571
11653
  const iter = parseInt(parts[0], 10);
11572
11654
  const storedCommit = parts[1] ?? "";
@@ -11591,13 +11673,13 @@ function checkMaxIterations(currentCommit, maxIterations = MAX_ITERATIONS, conte
11591
11673
  return { skip: null, iteration };
11592
11674
  }
11593
11675
  function writeIteration(iteration, commit, contentHash) {
11594
- (0, import_node_fs4.mkdirSync)(GATE_DIR, { recursive: true });
11595
- (0, import_node_fs4.writeFileSync)(ITERATION_FILE, `${iteration}:${commit}:${contentHash ?? ""}`);
11676
+ (0, import_node_fs5.mkdirSync)(GATE_DIR, { recursive: true });
11677
+ (0, import_node_fs5.writeFileSync)(ITERATION_FILE, `${iteration}:${commit}:${contentHash ?? ""}`);
11596
11678
  }
11597
11679
 
11598
11680
  // src/lib/static-analysis.ts
11599
- var import_node_child_process5 = require("node:child_process");
11600
- var import_node_fs5 = require("node:fs");
11681
+ var import_node_child_process6 = require("node:child_process");
11682
+ var import_node_fs6 = require("node:fs");
11601
11683
  var SEVERITY_ORDER = {
11602
11684
  Error: 0,
11603
11685
  Critical: 0,
@@ -11609,7 +11691,7 @@ var SEVERITY_ORDER = {
11609
11691
  };
11610
11692
  function isCodacyAvailable() {
11611
11693
  try {
11612
- (0, import_node_child_process5.execSync)("which codacy-analysis", { stdio: "pipe" });
11694
+ (0, import_node_child_process6.execSync)("which codacy-analysis", { stdio: "pipe" });
11613
11695
  return true;
11614
11696
  } catch {
11615
11697
  return false;
@@ -11624,7 +11706,7 @@ function runCodacyAnalysis(files) {
11624
11706
  if (files.length === 0) return empty;
11625
11707
  const existingFiles = files.filter((f) => {
11626
11708
  try {
11627
- return (0, import_node_fs5.existsSync)(f);
11709
+ return (0, import_node_fs6.existsSync)(f);
11628
11710
  } catch {
11629
11711
  return false;
11630
11712
  }
@@ -11633,7 +11715,7 @@ function runCodacyAnalysis(files) {
11633
11715
  const fileArgs = existingFiles.join(" ");
11634
11716
  let output;
11635
11717
  try {
11636
- output = (0, import_node_child_process5.execSync)(
11718
+ output = (0, import_node_child_process6.execSync)(
11637
11719
  `codacy-analysis analyze --install-dependencies --files ${fileArgs} --output-format json --log-level error --parallel-tools 3`,
11638
11720
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], maxBuffer: 10 * 1024 * 1024 }
11639
11721
  );
@@ -11686,7 +11768,7 @@ function runCodacyAnalysis(files) {
11686
11768
  }
11687
11769
 
11688
11770
  // src/lib/specs.ts
11689
- var import_node_fs6 = require("node:fs");
11771
+ var import_node_fs7 = require("node:fs");
11690
11772
  var import_node_path6 = require("node:path");
11691
11773
  var SPEC_CANDIDATES = [
11692
11774
  "CLAUDE.md",
@@ -11711,15 +11793,15 @@ function discoverSpecs() {
11711
11793
  if (result.length >= MAX_SPEC_FILES) return false;
11712
11794
  if (totalBytes >= MAX_TOTAL_SPEC_BYTES) return false;
11713
11795
  if (seen.has(specPath)) return true;
11714
- if (!(0, import_node_fs6.existsSync)(specPath)) return true;
11796
+ if (!(0, import_node_fs7.existsSync)(specPath)) return true;
11715
11797
  seen.add(specPath);
11716
11798
  const remaining = MAX_TOTAL_SPEC_BYTES - totalBytes;
11717
11799
  const readBytes = Math.min(MAX_SPEC_FILE_BYTES, remaining);
11718
11800
  try {
11719
11801
  const buf = Buffer.alloc(readBytes);
11720
- const fd = (0, import_node_fs6.openSync)(specPath, "r");
11721
- const bytesRead = (0, import_node_fs6.readSync)(fd, buf, 0, readBytes, 0);
11722
- (0, import_node_fs6.closeSync)(fd);
11802
+ const fd = (0, import_node_fs7.openSync)(specPath, "r");
11803
+ const bytesRead = (0, import_node_fs7.readSync)(fd, buf, 0, readBytes, 0);
11804
+ (0, import_node_fs7.closeSync)(fd);
11723
11805
  const content = buf.slice(0, bytesRead).toString("utf-8");
11724
11806
  if (!content) return true;
11725
11807
  result.push({ path: specPath, content });
@@ -11732,7 +11814,7 @@ function discoverSpecs() {
11732
11814
  if (!addSpec(candidate)) break;
11733
11815
  }
11734
11816
  for (const dir of ["spec", "docs"]) {
11735
- if (!(0, import_node_fs6.existsSync)(dir)) continue;
11817
+ if (!(0, import_node_fs7.existsSync)(dir)) continue;
11736
11818
  try {
11737
11819
  const mdFiles = findMdFiles(dir, 2).sort();
11738
11820
  for (const mdFile of mdFiles) {
@@ -11747,7 +11829,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
11747
11829
  if (depth >= maxDepth) return [];
11748
11830
  const result = [];
11749
11831
  try {
11750
- const entries = (0, import_node_fs6.readdirSync)(dir, { withFileTypes: true });
11832
+ const entries = (0, import_node_fs7.readdirSync)(dir, { withFileTypes: true });
11751
11833
  for (const entry of entries) {
11752
11834
  const fullPath = (0, import_node_path6.join)(dir, entry.name);
11753
11835
  if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -11762,13 +11844,13 @@ function findMdFiles(dir, maxDepth, depth = 0) {
11762
11844
  }
11763
11845
  function discoverPlans() {
11764
11846
  const plansDir = ".claude/plans";
11765
- if (!(0, import_node_fs6.existsSync)(plansDir)) return [];
11847
+ if (!(0, import_node_fs7.existsSync)(plansDir)) return [];
11766
11848
  const result = [];
11767
11849
  try {
11768
- const entries = (0, import_node_fs6.readdirSync)(plansDir).filter((f) => f.endsWith(".md")).map((f) => {
11850
+ const entries = (0, import_node_fs7.readdirSync)(plansDir).filter((f) => f.endsWith(".md")).map((f) => {
11769
11851
  const fullPath = (0, import_node_path6.join)(plansDir, f);
11770
11852
  try {
11771
- const stat = (0, import_node_fs6.statSync)(fullPath);
11853
+ const stat = (0, import_node_fs7.statSync)(fullPath);
11772
11854
  return { name: f, path: fullPath, mtime: stat.mtimeMs, size: stat.size };
11773
11855
  } catch {
11774
11856
  return null;
@@ -11777,7 +11859,7 @@ function discoverPlans() {
11777
11859
  for (const entry of entries) {
11778
11860
  if (entry.size > MAX_PLAN_FILE_BYTES) continue;
11779
11861
  try {
11780
- const content = (0, import_node_fs6.readFileSync)(entry.path, "utf-8");
11862
+ const content = (0, import_node_fs7.readFileSync)(entry.path, "utf-8");
11781
11863
  result.push({ name: entry.name, content });
11782
11864
  } catch {
11783
11865
  }
@@ -11787,15 +11869,113 @@ function discoverPlans() {
11787
11869
  return result;
11788
11870
  }
11789
11871
 
11872
+ // src/lib/snapshot.ts
11873
+ var import_node_fs8 = require("node:fs");
11874
+ var import_node_path7 = require("node:path");
11875
+ var import_node_child_process7 = require("node:child_process");
11876
+ function generateSnapshotDiffs(files) {
11877
+ if (!(0, import_node_fs8.existsSync)(SNAPSHOT_DIR)) {
11878
+ return { diffs: [], has_snapshots: false };
11879
+ }
11880
+ const diffs = [];
11881
+ for (const file of files) {
11882
+ const snapshotPath = (0, import_node_path7.join)(SNAPSHOT_DIR, file.path);
11883
+ const language = file.language ?? detectLanguage(file.path);
11884
+ if ((0, import_node_fs8.existsSync)(snapshotPath)) {
11885
+ const oldContent = (0, import_node_fs8.readFileSync)(snapshotPath, "utf-8");
11886
+ if (oldContent === file.content) continue;
11887
+ const diff = computeDiff(oldContent, file.content, file.path);
11888
+ if (diff) {
11889
+ diffs.push({ path: file.path, language, diff, status: "modified" });
11890
+ }
11891
+ } else {
11892
+ const addedLines = file.content.split("\n").map((l) => `+${l}`).join("\n");
11893
+ diffs.push({
11894
+ path: file.path,
11895
+ language,
11896
+ diff: `--- /dev/null
11897
+ +++ b/${file.path}
11898
+ @@ -0,0 +1,${file.content.split("\n").length} @@
11899
+ ${addedLines}`,
11900
+ status: "added"
11901
+ });
11902
+ }
11903
+ }
11904
+ return { diffs, has_snapshots: true };
11905
+ }
11906
+ function saveSnapshots(files) {
11907
+ const snapshotPaths = /* @__PURE__ */ new Set();
11908
+ for (const file of files) {
11909
+ const snapshotPath = (0, import_node_path7.join)(SNAPSHOT_DIR, file.path);
11910
+ snapshotPaths.add(snapshotPath);
11911
+ (0, import_node_fs8.mkdirSync)((0, import_node_path7.dirname)(snapshotPath), { recursive: true });
11912
+ (0, import_node_fs8.writeFileSync)(snapshotPath, file.content);
11913
+ }
11914
+ cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
11915
+ }
11916
+ function computeDiff(oldContent, newContent, filePath) {
11917
+ const tmpOld = (0, import_node_path7.join)(SNAPSHOT_DIR, ".diff-old.tmp");
11918
+ const tmpNew = (0, import_node_path7.join)(SNAPSHOT_DIR, ".diff-new.tmp");
11919
+ try {
11920
+ (0, import_node_fs8.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
11921
+ (0, import_node_fs8.writeFileSync)(tmpOld, oldContent);
11922
+ (0, import_node_fs8.writeFileSync)(tmpNew, newContent);
11923
+ const result = (0, import_node_child_process7.execSync)(
11924
+ `git diff --no-index --unified=3 -- "${tmpOld}" "${tmpNew}"`,
11925
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
11926
+ );
11927
+ return result || null;
11928
+ } catch (err) {
11929
+ const error = err;
11930
+ if (error.status === 1 && error.stdout) {
11931
+ return error.stdout.replace(/^diff --git a\/.*$/m, `diff --git a/${filePath} b/${filePath}`).replace(/^--- a\/.*$/m, `--- a/${filePath}`).replace(/^\+\+\+ b\/.*$/m, `+++ b/${filePath}`);
11932
+ }
11933
+ return null;
11934
+ } finally {
11935
+ try {
11936
+ (0, import_node_fs8.unlinkSync)(tmpOld);
11937
+ } catch {
11938
+ }
11939
+ try {
11940
+ (0, import_node_fs8.unlinkSync)(tmpNew);
11941
+ } catch {
11942
+ }
11943
+ }
11944
+ }
11945
+ function cleanStaleSnapshots(dir, keepSet) {
11946
+ if (!(0, import_node_fs8.existsSync)(dir)) return;
11947
+ try {
11948
+ const entries = (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true });
11949
+ for (const entry of entries) {
11950
+ if (entry.name.startsWith(".")) continue;
11951
+ const fullPath = (0, import_node_path7.join)(dir, entry.name);
11952
+ if (entry.isDirectory()) {
11953
+ cleanStaleSnapshots(fullPath, keepSet);
11954
+ try {
11955
+ const remaining = (0, import_node_fs8.readdirSync)(fullPath);
11956
+ if (remaining.length === 0) (0, import_node_fs8.rmdirSync)(fullPath);
11957
+ } catch {
11958
+ }
11959
+ } else if (!keepSet.has(fullPath)) {
11960
+ try {
11961
+ (0, import_node_fs8.unlinkSync)(fullPath);
11962
+ } catch {
11963
+ }
11964
+ }
11965
+ }
11966
+ } catch {
11967
+ }
11968
+ }
11969
+
11790
11970
  // src/lib/offline.ts
11791
- var import_node_fs7 = require("node:fs");
11971
+ var import_node_fs9 = require("node:fs");
11792
11972
  var import_node_crypto2 = require("node:crypto");
11793
11973
  function cacheRequest(body) {
11794
11974
  try {
11795
- (0, import_node_fs7.mkdirSync)(CACHE_DIR, { recursive: true });
11975
+ (0, import_node_fs9.mkdirSync)(CACHE_DIR, { recursive: true });
11796
11976
  const suffix = (0, import_node_crypto2.randomBytes)(4).toString("hex");
11797
11977
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
11798
- (0, import_node_fs7.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(body));
11978
+ (0, import_node_fs9.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(body));
11799
11979
  } catch {
11800
11980
  }
11801
11981
  }
@@ -11824,7 +12004,7 @@ function registerAnalyzeCommand(program2) {
11824
12004
  });
11825
12005
  }
11826
12006
  async function runAnalyze(opts, globals) {
11827
- const allChanged = getChangedFiles();
12007
+ const { files: allChanged, hasRecentCommitFiles } = getChangedFiles();
11828
12008
  const analyzable = filterAnalyzable(allChanged);
11829
12009
  const reviewable = filterReviewable(allChanged);
11830
12010
  const securityFiles = filterSecurity(allChanged);
@@ -11836,13 +12016,13 @@ async function runAnalyze(opts, globals) {
11836
12016
  const debounceSkip = checkDebounce(debounceSeconds);
11837
12017
  if (debounceSkip) passAndExit(debounceSkip);
11838
12018
  const allCheckable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...reviewable, ...securityFiles]));
11839
- const mtimeSkip = checkMtime(allCheckable);
12019
+ const mtimeSkip = checkMtime(allCheckable, hasRecentCommitFiles);
11840
12020
  if (mtimeSkip) passAndExit(mtimeSkip);
11841
12021
  recordAnalysisStart();
11842
12022
  const { skip: hashSkip, hash: contentHash } = checkContentHash(allCheckable);
11843
12023
  if (hashSkip) passAndExit(hashSkip);
11844
12024
  const recentForReview = narrowToRecent(allForReview);
11845
- const intent = await readAndClearIntent();
12025
+ const conversation = await readAndClearConversationBuffer();
11846
12026
  const specs = discoverSpecs();
11847
12027
  const plans = discoverPlans();
11848
12028
  let staticResults;
@@ -11864,6 +12044,7 @@ async function runAnalyze(opts, globals) {
11864
12044
  if (codeDelta.files.length === 0 && staticResults.findings.length === 0) {
11865
12045
  passAndExit("No files within size limits to analyze");
11866
12046
  }
12047
+ const snapshotResult = generateSnapshotDiffs(codeDelta.files);
11867
12048
  const tokenResult = await resolveToken(globals.token);
11868
12049
  if (!tokenResult.ok) {
11869
12050
  passAndExit("Not configured yet \u2014 run /gate-setup in Claude Code to enable quality gates.");
@@ -11888,13 +12069,23 @@ async function runAnalyze(opts, globals) {
11888
12069
  iteration
11889
12070
  }
11890
12071
  };
11891
- const hasIntent = intent?.prompt || specs.length > 0 || plans.length > 0;
12072
+ if (snapshotResult.has_snapshots && snapshotResult.diffs.length > 0) {
12073
+ requestBody.snapshot_diffs = snapshotResult.diffs;
12074
+ }
12075
+ const hasIntent = (conversation?.prompts?.length ?? 0) > 0 || specs.length > 0 || plans.length > 0;
11892
12076
  if (hasIntent) {
11893
12077
  const intentContext = {};
11894
- if (intent?.prompt) {
11895
- intentContext.user_prompt = intent.prompt;
11896
- intentContext.session_id = intent.session_id || void 0;
11897
- intentContext.prompt_captured_at = intent.captured_at || void 0;
12078
+ if (conversation && conversation.prompts.length > 0) {
12079
+ const latest = conversation.prompts[conversation.prompts.length - 1];
12080
+ intentContext.user_prompt = latest.prompt;
12081
+ intentContext.session_id = latest.session_id || void 0;
12082
+ intentContext.prompt_captured_at = latest.captured_at || void 0;
12083
+ if (conversation.prompts.length > 1) {
12084
+ intentContext.conversation = conversation.prompts;
12085
+ }
12086
+ if (conversation.recent_commits.length > 0) {
12087
+ intentContext.recent_commits = conversation.recent_commits;
12088
+ }
11898
12089
  }
11899
12090
  if (specs.length > 0) intentContext.specs = specs;
11900
12091
  if (plans.length > 0) intentContext.plans = plans;
@@ -11923,6 +12114,7 @@ async function runAnalyze(opts, globals) {
11923
12114
  }
11924
12115
  const response = result.data;
11925
12116
  const decision = response.gate_decision ?? "PASS";
12117
+ saveSnapshots(codeDelta.files.map((f) => ({ path: f.path, content: f.content })));
11926
12118
  switch (decision) {
11927
12119
  case "FAIL": {
11928
12120
  writeIteration(iteration + 1, currentCommit, contentHash ?? void 0);
@@ -12008,7 +12200,7 @@ async function runAnalyze(opts, globals) {
12008
12200
  }
12009
12201
 
12010
12202
  // src/commands/review.ts
12011
- var import_node_fs8 = require("node:fs");
12203
+ var import_node_fs10 = require("node:fs");
12012
12204
  function registerReviewCommand(program2) {
12013
12205
  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) => {
12014
12206
  const globals = program2.opts();
@@ -12027,7 +12219,7 @@ async function runReview(opts, globals) {
12027
12219
  const securityFiles = filterSecurity(allFiles);
12028
12220
  let staticResults;
12029
12221
  if (isCodacyAvailable()) {
12030
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs8.existsSync)(f) || resolveFile(f) !== null);
12222
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs10.existsSync)(f) || resolveFile(f) !== null);
12031
12223
  staticResults = runCodacyAnalysis(scannable);
12032
12224
  } else {
12033
12225
  staticResults = {
@@ -12052,10 +12244,10 @@ async function runReview(opts, globals) {
12052
12244
  const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
12053
12245
  specs = [];
12054
12246
  for (const p of specPaths) {
12055
- if (!(0, import_node_fs8.existsSync)(p)) continue;
12247
+ if (!(0, import_node_fs10.existsSync)(p)) continue;
12056
12248
  try {
12057
- const { readFileSync: readFileSync4 } = await import("node:fs");
12058
- const content = readFileSync4(p, "utf-8");
12249
+ const { readFileSync: readFileSync5 } = await import("node:fs");
12250
+ const content = readFileSync5(p, "utf-8");
12059
12251
  specs.push({ path: p, content: content.slice(0, 10240) });
12060
12252
  } catch {
12061
12253
  }
@@ -12113,21 +12305,21 @@ async function runReview(opts, globals) {
12113
12305
  }
12114
12306
 
12115
12307
  // src/commands/init.ts
12116
- var import_node_fs9 = require("node:fs");
12308
+ var import_node_fs11 = require("node:fs");
12117
12309
  var import_promises8 = require("node:fs/promises");
12118
- var import_node_path7 = require("node:path");
12119
- var import_node_child_process6 = require("node:child_process");
12310
+ var import_node_path8 = require("node:path");
12311
+ var import_node_child_process8 = require("node:child_process");
12120
12312
  function resolveDataDir() {
12121
12313
  const candidates = [
12122
- (0, import_node_path7.join)(__dirname, "..", "data"),
12314
+ (0, import_node_path8.join)(__dirname, "..", "data"),
12123
12315
  // installed: node_modules/@codacy/gate-cli/data
12124
- (0, import_node_path7.join)(__dirname, "..", "..", "data"),
12316
+ (0, import_node_path8.join)(__dirname, "..", "..", "data"),
12125
12317
  // edge case: nested resolution
12126
- (0, import_node_path7.join)(process.cwd(), "cli", "data")
12318
+ (0, import_node_path8.join)(process.cwd(), "cli", "data")
12127
12319
  // local dev: running from repo root
12128
12320
  ];
12129
12321
  for (const candidate of candidates) {
12130
- if ((0, import_node_fs9.existsSync)((0, import_node_path7.join)(candidate, "skills"))) {
12322
+ if ((0, import_node_fs11.existsSync)((0, import_node_path8.join)(candidate, "skills"))) {
12131
12323
  return candidate;
12132
12324
  }
12133
12325
  }
@@ -12143,7 +12335,7 @@ function registerInitCommand(program2) {
12143
12335
  program2.command("init").description("Initialize GATE.md in the current project").option("--force", "Overwrite existing skills and hooks").action(async (opts) => {
12144
12336
  const force = opts.force ?? false;
12145
12337
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
12146
- const isProject = projectMarkers.some((m) => (0, import_node_fs9.existsSync)(m));
12338
+ const isProject = projectMarkers.some((m) => (0, import_node_fs11.existsSync)(m));
12147
12339
  if (!isProject) {
12148
12340
  printError("No project detected in the current directory.");
12149
12341
  printInfo('Run "gate init" from your project root.');
@@ -12161,30 +12353,30 @@ function registerInitCommand(program2) {
12161
12353
  }
12162
12354
  printInfo(` Node.js ${nodeVersion} \u2713`);
12163
12355
  try {
12164
- const gitVersion = (0, import_node_child_process6.execSync)("git --version", { encoding: "utf-8" }).trim();
12356
+ const gitVersion = (0, import_node_child_process8.execSync)("git --version", { encoding: "utf-8" }).trim();
12165
12357
  printInfo(` ${gitVersion} \u2713`);
12166
12358
  } catch {
12167
12359
  printError("git is required but not installed. Install from https://git-scm.com");
12168
12360
  process.exit(1);
12169
12361
  }
12170
12362
  try {
12171
- (0, import_node_child_process6.execSync)("which claude", { encoding: "utf-8" });
12363
+ (0, import_node_child_process8.execSync)("which claude", { encoding: "utf-8" });
12172
12364
  printInfo(" Claude Code \u2713");
12173
12365
  } catch {
12174
12366
  printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
12175
12367
  }
12176
12368
  try {
12177
- (0, import_node_child_process6.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
12369
+ (0, import_node_child_process8.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
12178
12370
  printInfo(" @codacy/analysis-cli \u2713");
12179
12371
  } catch {
12180
12372
  printInfo(" Installing @codacy/analysis-cli...");
12181
12373
  try {
12182
- (0, import_node_child_process6.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
12374
+ (0, import_node_child_process8.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
12183
12375
  printInfo(" @codacy/analysis-cli installed \u2713");
12184
12376
  } catch {
12185
12377
  try {
12186
12378
  printWarn(" Retrying with sudo...");
12187
- (0, import_node_child_process6.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
12379
+ (0, import_node_child_process8.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
12188
12380
  printInfo(" @codacy/analysis-cli installed \u2713");
12189
12381
  } catch {
12190
12382
  printWarn(" Could not install @codacy/analysis-cli automatically.");
@@ -12196,21 +12388,21 @@ function registerInitCommand(program2) {
12196
12388
  console.log("");
12197
12389
  printInfo("Installing skills...");
12198
12390
  const dataDir = resolveDataDir();
12199
- const skillsSource = (0, import_node_path7.join)(dataDir, "skills");
12391
+ const skillsSource = (0, import_node_path8.join)(dataDir, "skills");
12200
12392
  const skillsDest = ".claude/skills";
12201
12393
  const skills = ["gate-setup", "gate-analyze", "gate-status", "gate-feedback"];
12202
12394
  let skillsInstalled = 0;
12203
12395
  for (const skill of skills) {
12204
- const src = (0, import_node_path7.join)(skillsSource, skill);
12205
- const dest = (0, import_node_path7.join)(skillsDest, skill);
12206
- if (!(0, import_node_fs9.existsSync)(src)) {
12396
+ const src = (0, import_node_path8.join)(skillsSource, skill);
12397
+ const dest = (0, import_node_path8.join)(skillsDest, skill);
12398
+ if (!(0, import_node_fs11.existsSync)(src)) {
12207
12399
  printWarn(` Skill data not found: ${skill}`);
12208
12400
  continue;
12209
12401
  }
12210
- if ((0, import_node_fs9.existsSync)(dest) && !force) {
12211
- const srcSkill = (0, import_node_path7.join)(src, "SKILL.md");
12212
- const destSkill = (0, import_node_path7.join)(dest, "SKILL.md");
12213
- if ((0, import_node_fs9.existsSync)(destSkill)) {
12402
+ if ((0, import_node_fs11.existsSync)(dest) && !force) {
12403
+ const srcSkill = (0, import_node_path8.join)(src, "SKILL.md");
12404
+ const destSkill = (0, import_node_path8.join)(dest, "SKILL.md");
12405
+ if ((0, import_node_fs11.existsSync)(destSkill)) {
12214
12406
  try {
12215
12407
  const srcContent = await (0, import_promises8.readFile)(srcSkill, "utf-8");
12216
12408
  const destContent = await (0, import_promises8.readFile)(destSkill, "utf-8");
@@ -12238,7 +12430,7 @@ function registerInitCommand(program2) {
12238
12430
  printInfo(' Run "gate hooks install --force" to overwrite.');
12239
12431
  }
12240
12432
  await (0, import_promises8.mkdir)(GATE_DIR, { recursive: true });
12241
- const globalGateDir = (0, import_node_path7.join)(process.env.HOME ?? "", ".gate");
12433
+ const globalGateDir = (0, import_node_path8.join)(process.env.HOME ?? "", ".gate");
12242
12434
  await (0, import_promises8.mkdir)(globalGateDir, { recursive: true });
12243
12435
  console.log("");
12244
12436
  printInfo("GATE.md initialized!");
@@ -12256,7 +12448,7 @@ function registerInitCommand(program2) {
12256
12448
  }
12257
12449
 
12258
12450
  // src/cli.ts
12259
- program.name("gate").description("CLI for GATE.md quality gate service").version("0.4.0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
12451
+ program.name("gate").description("CLI for GATE.md quality gate service").version("0.7.0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
12260
12452
  registerAuthCommands(program);
12261
12453
  registerHooksCommands(program);
12262
12454
  registerIntentCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/gate-cli",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "CLI for GATE.md quality gate service",
5
5
  "bin": {
6
6
  "gate": "./bin/gate.js"
@@ -15,7 +15,7 @@
15
15
  "node": ">=20"
16
16
  },
17
17
  "scripts": {
18
- "build": "esbuild src/cli.ts --bundle --platform=node --target=node20 --outfile=bin/gate.js --format=cjs --banner:js=\"#!/usr/bin/env node\"",
18
+ "build": "node scripts/build.js",
19
19
  "test": "node --import tsx --test $(find tests -name '*.test.ts' | sort)",
20
20
  "typecheck": "tsc --noEmit",
21
21
  "prepublishOnly": "npm run typecheck && npm run build"