@driftless-sh/cli 0.1.19 → 0.1.21

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/dist/index.js CHANGED
@@ -126140,7 +126140,7 @@ ${lanes.join("\n")}
126140
126140
  }
126141
126141
  }
126142
126142
  function createImportCallExpressionAMD(arg, containsLexicalThis) {
126143
- const resolve7 = factory2.createUniqueName("resolve");
126143
+ const resolve8 = factory2.createUniqueName("resolve");
126144
126144
  const reject = factory2.createUniqueName("reject");
126145
126145
  const parameters = [
126146
126146
  factory2.createParameterDeclaration(
@@ -126149,7 +126149,7 @@ ${lanes.join("\n")}
126149
126149
  /*dotDotDotToken*/
126150
126150
  void 0,
126151
126151
  /*name*/
126152
- resolve7
126152
+ resolve8
126153
126153
  ),
126154
126154
  factory2.createParameterDeclaration(
126155
126155
  /*modifiers*/
@@ -126166,7 +126166,7 @@ ${lanes.join("\n")}
126166
126166
  factory2.createIdentifier("require"),
126167
126167
  /*typeArguments*/
126168
126168
  void 0,
126169
- [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve7, reject]
126169
+ [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve8, reject]
126170
126170
  )
126171
126171
  )
126172
126172
  ]);
@@ -212884,8 +212884,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
212884
212884
  installPackage(options) {
212885
212885
  this.packageInstallId++;
212886
212886
  const request2 = { kind: "installPackage", ...options, id: this.packageInstallId };
212887
- const promise = new Promise((resolve7, reject) => {
212888
- (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve7, reject });
212887
+ const promise = new Promise((resolve8, reject) => {
212888
+ (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map())).set(this.packageInstallId, { resolve: resolve8, reject });
212889
212889
  });
212890
212890
  this.installer.send(request2);
212891
212891
  return promise;
@@ -214179,6 +214179,8 @@ var require_dist = __commonJS({
214179
214179
  return enricher_1.enrichComponents;
214180
214180
  } });
214181
214181
  async function scanRepo2(rootPath) {
214182
+ const startMs = Date.now();
214183
+ const startMem = process.memoryUsage().heapUsed;
214182
214184
  const identity = (0, identity_1.identifyRepo)(rootPath);
214183
214185
  let components = (0, nestjs_extractor_1.extractNestJS)(rootPath);
214184
214186
  components = await (0, enricher_1.enrichComponents)(components);
@@ -214191,7 +214193,18 @@ var require_dist = __commonJS({
214191
214193
  total_modules: components.filter((c) => c.type === "module").length,
214192
214194
  total_dtos: components.filter((c) => c.type === "dto").length
214193
214195
  };
214194
- return { identity, components, stats };
214196
+ const durationMs = Date.now() - startMs;
214197
+ const memoryMb = Math.round((process.memoryUsage().heapUsed - startMem) / 1024 / 1024);
214198
+ return {
214199
+ identity,
214200
+ components,
214201
+ stats,
214202
+ telemetry: {
214203
+ duration_ms: durationMs,
214204
+ memory_mb: memoryMb,
214205
+ files_parsed: uniqueFiles.size
214206
+ }
214207
+ };
214195
214208
  }
214196
214209
  }
214197
214210
  });
@@ -214230,8 +214243,30 @@ function getBaseUrl() {
214230
214243
  }
214231
214244
  return DEFAULT_URL;
214232
214245
  }
214246
+ function parseError(e) {
214247
+ const msg = e.message;
214248
+ const jsonMatch = msg.match(/\{[^}]*"message"[^}]*\}/);
214249
+ if (jsonMatch) {
214250
+ try {
214251
+ const parsed = JSON.parse(jsonMatch[0]);
214252
+ if (parsed.message) return parsed.message;
214253
+ } catch {
214254
+ }
214255
+ }
214256
+ const statusMatch = msg.match(/HTTP (\d+):/);
214257
+ if (statusMatch) {
214258
+ const code = parseInt(statusMatch[1], 10);
214259
+ if (code === 500) return "Internal server error \u2014 the API encountered an unexpected issue";
214260
+ if (code === 401) return "Authentication failed \u2014 check your API key";
214261
+ if (code === 403) return "Access denied \u2014 your API key lacks permission";
214262
+ if (code === 404) return "Not found \u2014 the resource does not exist";
214263
+ if (code === 429) return "Rate limited \u2014 too many requests, try again later";
214264
+ return `Server error (HTTP ${code})`;
214265
+ }
214266
+ return msg;
214267
+ }
214233
214268
  function request(method, path, body) {
214234
- return new Promise((resolve7, reject) => {
214269
+ return new Promise((resolve8, reject) => {
214235
214270
  const baseUrl = getBaseUrl();
214236
214271
  const fullUrl = `${baseUrl}${path}`;
214237
214272
  const url = new URL(fullUrl);
@@ -214257,14 +214292,14 @@ function request(method, path, body) {
214257
214292
  return;
214258
214293
  }
214259
214294
  try {
214260
- resolve7(JSON.parse(data));
214295
+ resolve8(JSON.parse(data));
214261
214296
  } catch {
214262
- resolve7(data);
214297
+ resolve8(data);
214263
214298
  }
214264
214299
  });
214265
214300
  }
214266
214301
  );
214267
- req.on("error", reject);
214302
+ req.on("error", (e) => reject(new Error(`Connection failed: ${e.message}`)));
214268
214303
  if (body) req.write(JSON.stringify(body));
214269
214304
  req.end();
214270
214305
  });
@@ -214282,6 +214317,9 @@ function getApiUrl() {
214282
214317
  function getApiKey() {
214283
214318
  return loadApiKey();
214284
214319
  }
214320
+ function formatError(e) {
214321
+ return parseError(e);
214322
+ }
214285
214323
 
214286
214324
  // src/git.ts
214287
214325
  var import_node_child_process = require("node:child_process");
@@ -214516,6 +214554,15 @@ function generateSmartRules(repoId, patterns) {
214516
214554
  scope: { paths: ["apps/", "libs/"] },
214517
214555
  pattern: { type: "FORBIDDEN_IMPORT", params: { imports: ["@modelcontextprotocol", "mcp"] } },
214518
214556
  repo_id: repoId
214557
+ },
214558
+ {
214559
+ name: "Controllers must be thin",
214560
+ description: "Controllers should only handle routing and validation. Move business logic, token manipulation, and debug code to services.",
214561
+ type: "STRUCTURAL",
214562
+ severity: "high",
214563
+ scope: { file_patterns: ["*.controller.ts"] },
214564
+ pattern: { type: "CONTROLLER_THICK", params: {} },
214565
+ repo_id: repoId
214519
214566
  }
214520
214567
  );
214521
214568
  return rules;
@@ -214677,12 +214724,24 @@ async function initCommand(args) {
214677
214724
  (sum, component) => sum + (component.relations?.length || 0),
214678
214725
  0
214679
214726
  );
214680
- console.log(` Framework: ${summary.framework} | Endpoints: ${summary.endpoints} | Services: ${summary.services}`);
214681
- console.log(` Modules: ${summary.modules} | Guards: ${summary.guards}`);
214727
+ const actualEndpoints = components.filter((c) => c.type === "endpoint").length;
214728
+ const actualServices = components.filter((c) => c.type === "service").length;
214729
+ const actualModules = components.filter((c) => c.type === "module").length;
214730
+ const actualGuards = components.filter((c) => c.type === "guard").length;
214731
+ const actualControllers = components.filter((c) => c.type === "controller").length;
214732
+ const actualDtos = components.filter((c) => c.type === "dto").length;
214733
+ console.log(` Framework: ${summary.framework} | Endpoints: ${actualEndpoints} | Services: ${actualServices}`);
214734
+ console.log(` Modules: ${actualModules} | Guards: ${actualGuards}`);
214682
214735
  console.log(` Relations: ${relationCount}`);
214736
+ if (actualControllers > 0) console.log(` Controllers: ${actualControllers}`);
214737
+ if (actualDtos > 0) console.log(` DTOs: ${actualDtos}`);
214683
214738
  if (summary.auth_patterns.length > 0) {
214684
214739
  console.log(` Auth: ${summary.auth_patterns.join(", ")}`);
214685
214740
  }
214741
+ if (scanResult.telemetry) {
214742
+ const t = scanResult.telemetry;
214743
+ console.log(` Scan: ${t.duration_ms}ms, ${t.memory_mb}MB heap, ${t.files_parsed} files`);
214744
+ }
214686
214745
  let repo;
214687
214746
  try {
214688
214747
  const repos = await api.get(`/workspaces/${workspaceSlug}/repos`);
@@ -214787,7 +214846,7 @@ Creating ${smartRules.length} architectural rules...`);
214787
214846
  }
214788
214847
  console.log(` Docs anchored: ${docsAnchored}`);
214789
214848
  console.log("\n---");
214790
- console.log(`Architecture: ${summary.modules} modules, ${summary.endpoints} endpoints, ${summary.services} services`);
214849
+ console.log(`Architecture: ${actualModules} modules, ${actualEndpoints} endpoints, ${actualServices} services`);
214791
214850
  console.log(`Relations: ${relationCount} cross-component dependencies mapped`);
214792
214851
  console.log(`Rules: ${rulesCreated} architectural rules created from code analysis`);
214793
214852
  console.log(`Watchers: ${watchersCreated} context watchers auto-generated`);
@@ -214832,6 +214891,7 @@ async function scanCommand(args) {
214832
214891
  const onlyDiff = args.includes("--diff");
214833
214892
  let diff = "";
214834
214893
  let source = "";
214894
+ let changedFiles = [];
214835
214895
  if (onlyDiff) {
214836
214896
  diff = getUncommittedDiff();
214837
214897
  source = "uncommitted changes";
@@ -214839,6 +214899,7 @@ async function scanCommand(args) {
214839
214899
  console.log("No uncommitted changes. Clean.");
214840
214900
  process.exit(0);
214841
214901
  }
214902
+ changedFiles = diff.split("\n").filter((line) => line.startsWith("+++ b/") || line.startsWith("--- a/")).map((line) => line.replace(/^\+\+\+ b\//, "").replace(/^--- a\//, "")).filter((f, i, arr) => arr.indexOf(f) === i);
214842
214903
  } else {
214843
214904
  const staged = getStagedDiff();
214844
214905
  const unstaged = getUncommittedDiff();
@@ -214852,6 +214913,9 @@ async function scanCommand(args) {
214852
214913
  const commitHash = getLastCommitHash();
214853
214914
  const author = getAuthorName();
214854
214915
  console.log(`Scanning ${source}...`);
214916
+ if (changedFiles.length > 0) {
214917
+ console.log(` Files: ${changedFiles.join(", ")}`);
214918
+ }
214855
214919
  const result = await api.post("/scan", {
214856
214920
  workspace_id: workspace.workspace_id,
214857
214921
  repo_id: repo.id,
@@ -214859,16 +214923,17 @@ async function scanCommand(args) {
214859
214923
  commit_hash: commitHash,
214860
214924
  author
214861
214925
  });
214926
+ const rulesEvaluated = result.rules_evaluated || 0;
214862
214927
  if (result.status === "clean") {
214863
- console.log("Clean \u2014 no violations detected.");
214928
+ console.log(`Clean \u2014 ${rulesEvaluated} rule(s) evaluated, no violations.`);
214864
214929
  process.exit(0);
214865
214930
  }
214866
214931
  if (!result.violations || result.violations.length === 0) {
214867
- console.log("Clean \u2014 no violations detected.");
214932
+ console.log(`Clean \u2014 ${rulesEvaluated} rule(s) evaluated, no violations.`);
214868
214933
  process.exit(0);
214869
214934
  }
214870
214935
  console.log(`
214871
- ${result.violations.length} violation(s) found:
214936
+ ${result.violations.length} violation(s) found (${rulesEvaluated} rule(s) evaluated):
214872
214937
  `);
214873
214938
  for (const v of result.violations) {
214874
214939
  const severityColor = v.severity === "critical" || v.severity === "high" ? "\x1B[31m" : "\x1B[33m";
@@ -214883,6 +214948,8 @@ ${result.violations.length} violation(s) found:
214883
214948
  }
214884
214949
 
214885
214950
  // src/commands/context.ts
214951
+ var import_node_fs4 = require("node:fs");
214952
+ var import_node_path4 = require("node:path");
214886
214953
  function parseArgs(args) {
214887
214954
  const flags = {};
214888
214955
  const positional = [];
@@ -215065,13 +215132,16 @@ async function contextCommand(args) {
215065
215132
  const qs = query.length > 0 ? `?${query.join("&")}` : "";
215066
215133
  try {
215067
215134
  const summaries = await api.get(`/workspaces/${workspaceSlug}/watchers${qs}`);
215135
+ if (summaries.length === 0) {
215136
+ console.error("No context topics yet. Run `driftless init` to auto-generate watchers from your codebase.");
215137
+ }
215068
215138
  if (isHuman) {
215069
215139
  renderSummaryHuman(summaries);
215070
215140
  } else {
215071
215141
  emitJSON(summaries);
215072
215142
  }
215073
215143
  } catch (e) {
215074
- console.error(`List failed: ${e.message}`);
215144
+ console.error(`List failed: ${formatError(e)}`);
215075
215145
  process.exit(1);
215076
215146
  }
215077
215147
  return;
@@ -215104,13 +215174,16 @@ async function contextCommand(args) {
215104
215174
  `/workspaces/${workspaceSlug}/watchers/match-files`,
215105
215175
  { files }
215106
215176
  );
215177
+ if (results.length === 0) {
215178
+ console.error(`No context topics match these files. No watcher covers the changed paths.`);
215179
+ }
215107
215180
  if (isHuman) {
215108
215181
  renderMatchFilesHuman(results, files);
215109
215182
  } else {
215110
215183
  emitJSON(results);
215111
215184
  }
215112
215185
  } catch (e) {
215113
- console.error(`Match failed: ${e.message}`);
215186
+ console.error(`Match failed: ${formatError(e)}`);
215114
215187
  process.exit(1);
215115
215188
  }
215116
215189
  return;
@@ -215126,7 +215199,11 @@ async function contextCommand(args) {
215126
215199
  if (isHuman) {
215127
215200
  renderContextHuman(ctx);
215128
215201
  } else {
215129
- emitJSON(ctx);
215202
+ const sanitized = JSON.parse(JSON.stringify(ctx, (_key, value) => {
215203
+ if (typeof value === "string" && value.length > 500) return value.slice(0, 500) + "\u2026";
215204
+ return value;
215205
+ }));
215206
+ emitJSON(sanitized);
215130
215207
  }
215131
215208
  } catch (e) {
215132
215209
  console.error(`Topic '${slug}' not found.`);
@@ -215144,13 +215221,16 @@ async function contextCommand(args) {
215144
215221
  const results = await api.get(
215145
215222
  `/workspaces/${workspaceSlug}/watchers/search?q=${encodeURIComponent(query)}`
215146
215223
  );
215224
+ if (results.length === 0) {
215225
+ console.error(`No context topics matching "${query}".`);
215226
+ }
215147
215227
  if (isHuman) {
215148
215228
  renderSummaryHuman(results);
215149
215229
  } else {
215150
215230
  emitJSON(results);
215151
215231
  }
215152
215232
  } catch (e) {
215153
- console.error(`Search failed: ${e.message}`);
215233
+ console.error(`Search failed: ${formatError(e)}`);
215154
215234
  process.exit(1);
215155
215235
  }
215156
215236
  return;
@@ -215324,10 +215404,14 @@ async function contextCommand(args) {
215324
215404
  if (filesFlag) console.log(` files: ${filesFlag}`);
215325
215405
  if (patternFlag) console.log(` pattern: ${patternFlag}`);
215326
215406
  } else {
215327
- emitJSON(result);
215407
+ const sanitized = JSON.parse(JSON.stringify(result, (_key, value) => {
215408
+ if (typeof value === "string" && value.length > 500) return value.slice(0, 500) + "\u2026";
215409
+ return value;
215410
+ }));
215411
+ emitJSON(sanitized);
215328
215412
  }
215329
215413
  } catch (e) {
215330
- console.error(`Anchor failed: ${e.message}`);
215414
+ console.error(`Anchor failed: ${formatError(e)}`);
215331
215415
  process.exit(1);
215332
215416
  }
215333
215417
  return;
@@ -215343,18 +215427,25 @@ async function contextCommand(args) {
215343
215427
  console.error("No files provided.");
215344
215428
  process.exit(1);
215345
215429
  }
215430
+ const missingFiles = files.filter((f) => !(0, import_node_fs4.existsSync)((0, import_node_path4.resolve)(process.cwd(), f)));
215431
+ if (missingFiles.length > 0 && isHuman) {
215432
+ console.error(`File(s) not found locally: ${missingFiles.join(", ")}. Matching by pattern only.`);
215433
+ }
215346
215434
  try {
215347
215435
  const results = await api.post(
215348
215436
  `/workspaces/${workspaceSlug}/watchers/match-files`,
215349
215437
  { files }
215350
215438
  );
215439
+ if (results.length === 0) {
215440
+ console.error(`No context topics match these files. No watcher covers the changed paths.`);
215441
+ }
215351
215442
  if (isHuman) {
215352
215443
  renderMatchFilesHuman(results, files);
215353
215444
  } else {
215354
215445
  emitJSON(results);
215355
215446
  }
215356
215447
  } catch (e) {
215357
- console.error(`Push failed: ${e.message}`);
215448
+ console.error(`Push failed: ${formatError(e)}`);
215358
215449
  process.exit(1);
215359
215450
  }
215360
215451
  return;
@@ -215365,8 +215456,8 @@ Run 'driftless help context' for full reference.`);
215365
215456
  }
215366
215457
 
215367
215458
  // src/commands/install-skill.ts
215368
- var import_node_fs4 = require("node:fs");
215369
- var import_node_path4 = require("node:path");
215459
+ var import_node_fs5 = require("node:fs");
215460
+ var import_node_path5 = require("node:path");
215370
215461
  var template = `# Driftless \u2014 Live Repo Context
215371
215462
 
215372
215463
  Driftless Cloud holds the team's living codebase context (topics, anchors, rules, gotchas).
@@ -215492,29 +215583,29 @@ Context delivery + structural verification only.
215492
215583
  `;
215493
215584
  function installSkillCommand() {
215494
215585
  const cwd = process.cwd();
215495
- const agentsPath = (0, import_node_path4.resolve)(cwd, "AGENTS.md");
215496
- if ((0, import_node_fs4.existsSync)(agentsPath)) {
215497
- const existing = (0, import_node_fs4.readFileSync)(agentsPath, "utf8");
215586
+ const agentsPath = (0, import_node_path5.resolve)(cwd, "AGENTS.md");
215587
+ if ((0, import_node_fs5.existsSync)(agentsPath)) {
215588
+ const existing = (0, import_node_fs5.readFileSync)(agentsPath, "utf8");
215498
215589
  if (existing.includes("# Driftless")) {
215499
215590
  console.log("Driftless section already present in AGENTS.md.");
215500
215591
  return;
215501
215592
  }
215502
- (0, import_node_fs4.writeFileSync)(agentsPath, existing + "\n---\n\n" + template);
215593
+ (0, import_node_fs5.writeFileSync)(agentsPath, existing + "\n---\n\n" + template);
215503
215594
  console.log(`Appended Driftless section to ${agentsPath}`);
215504
215595
  } else {
215505
- (0, import_node_fs4.writeFileSync)(agentsPath, template);
215596
+ (0, import_node_fs5.writeFileSync)(agentsPath, template);
215506
215597
  console.log(`Driftless skill installed at ${agentsPath}`);
215507
215598
  }
215508
215599
  }
215509
215600
 
215510
215601
  // src/commands/login.ts
215511
- var import_node_fs5 = require("node:fs");
215512
- var import_node_path5 = require("node:path");
215602
+ var import_node_fs6 = require("node:fs");
215603
+ var import_node_path6 = require("node:path");
215513
215604
  var import_node_readline = require("node:readline");
215514
215605
  var import_node_child_process2 = require("node:child_process");
215515
215606
  var import_node_os2 = require("node:os");
215516
- var CONFIG_DIR = (0, import_node_path5.resolve)((0, import_node_os2.homedir)(), ".driftless");
215517
- var CONFIG_PATH2 = (0, import_node_path5.resolve)(CONFIG_DIR, "config.json");
215607
+ var CONFIG_DIR = (0, import_node_path6.resolve)((0, import_node_os2.homedir)(), ".driftless");
215608
+ var CONFIG_PATH2 = (0, import_node_path6.resolve)(CONFIG_DIR, "config.json");
215518
215609
  function openBrowser(url) {
215519
215610
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
215520
215611
  (0, import_node_child_process2.exec)(`${cmd} ${url}`);
@@ -215543,10 +215634,10 @@ async function loginCommand(args) {
215543
215634
  input: process.stdin,
215544
215635
  output: process.stdout
215545
215636
  });
215546
- const apiKey = await new Promise((resolve7) => {
215637
+ const apiKey = await new Promise((resolve8) => {
215547
215638
  rl.question("Paste your API key: ", (answer) => {
215548
215639
  rl.close();
215549
- resolve7(answer.trim());
215640
+ resolve8(answer.trim());
215550
215641
  });
215551
215642
  });
215552
215643
  if (!apiKey.startsWith("drift_")) {
@@ -215559,10 +215650,10 @@ async function loginCommand(args) {
215559
215650
  function saveConfig(apiKey, apiUrl) {
215560
215651
  const url = apiUrl || "https://api.driftless.icu/api/v1";
215561
215652
  try {
215562
- if (!(0, import_node_fs5.existsSync)(CONFIG_DIR)) {
215563
- (0, import_node_fs5.mkdirSync)(CONFIG_DIR, { recursive: true });
215653
+ if (!(0, import_node_fs6.existsSync)(CONFIG_DIR)) {
215654
+ (0, import_node_fs6.mkdirSync)(CONFIG_DIR, { recursive: true });
215564
215655
  }
215565
- (0, import_node_fs5.writeFileSync)(
215656
+ (0, import_node_fs6.writeFileSync)(
215566
215657
  CONFIG_PATH2,
215567
215658
  JSON.stringify({ api_key: apiKey, api_url: url }, null, 2) + "\n"
215568
215659
  );
@@ -215578,8 +215669,8 @@ function saveConfig(apiKey, apiUrl) {
215578
215669
  }
215579
215670
 
215580
215671
  // src/commands/doctor.ts
215581
- var import_node_fs6 = require("node:fs");
215582
- var import_node_path6 = require("node:path");
215672
+ var import_node_fs7 = require("node:fs");
215673
+ var import_node_path7 = require("node:path");
215583
215674
  async function doctorCommand() {
215584
215675
  const checks = [];
215585
215676
  const apiKey = getApiKey();
@@ -215590,7 +215681,7 @@ async function doctorCommand() {
215590
215681
  }
215591
215682
  const apiUrl = getApiUrl();
215592
215683
  try {
215593
- await api.get("/me");
215684
+ await api.get("/health");
215594
215685
  checks.push({ name: "API reachable", status: "ok", detail: apiUrl });
215595
215686
  } catch {
215596
215687
  checks.push({ name: "API reachable", status: "fail", detail: `Cannot reach ${apiUrl}` });
@@ -215665,9 +215756,9 @@ async function doctorCommand() {
215665
215756
  } else {
215666
215757
  checks.push({ name: "Baseline", status: "warn", detail: "Skipped (no git remote)" });
215667
215758
  }
215668
- const agentsPath = (0, import_node_path6.resolve)(process.cwd(), "AGENTS.md");
215669
- if ((0, import_node_fs6.existsSync)(agentsPath)) {
215670
- const content = (0, import_node_fs6.readFileSync)(agentsPath, "utf-8");
215759
+ const agentsPath = (0, import_node_path7.resolve)(process.cwd(), "AGENTS.md");
215760
+ if ((0, import_node_fs7.existsSync)(agentsPath)) {
215761
+ const content = (0, import_node_fs7.readFileSync)(agentsPath, "utf-8");
215671
215762
  if (content.includes("driftless")) {
215672
215763
  checks.push({ name: "AGENTS.md", status: "ok", detail: "Driftless skill installed" });
215673
215764
  } else {
@@ -215722,7 +215813,7 @@ function pad2(s, n) {
215722
215813
  }
215723
215814
 
215724
215815
  // src/index.ts
215725
- var VERSION = "0.1.19";
215816
+ var VERSION = "0.1.21";
215726
215817
  var HELP_TEXT = `Driftless CLI v${VERSION} \u2014 Context integrity for AI engineering teams
215727
215818
 
215728
215819
  Install: npm install -g @driftless-sh/cli