@blockyfy/stg-cli 0.4.1 → 0.4.3

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
@@ -5,7 +5,7 @@ import { Command } from "commander";
5
5
  import chalk9 from "chalk";
6
6
  import {
7
7
  readFileSync as readFileSync7,
8
- existsSync as existsSync7,
8
+ existsSync as existsSync8,
9
9
  readdirSync,
10
10
  statSync,
11
11
  openSync,
@@ -13,7 +13,7 @@ import {
13
13
  closeSync
14
14
  } from "fs";
15
15
  import { readFile, stat as fsStat, open as fsOpen } from "fs/promises";
16
- import { resolve as resolve2, extname, join as join5, basename } from "path";
16
+ import { resolve as resolve2, extname, join as join6, basename } from "path";
17
17
  import os from "os";
18
18
 
19
19
  // src/types.ts
@@ -31,7 +31,7 @@ var DEFAULT_CONFIG = {
31
31
  { tokenType: "Property" /* Property */, prefix: "_prop" },
32
32
  { tokenType: "Method" /* Method */, prefix: "_fn" }
33
33
  ],
34
- storePath: `${process.env["HOME"] ?? "/tmp"}/.pretense`
34
+ storePath: `${process.env["HOME"] ?? "/tmp"}/.pretest`
35
35
  };
36
36
 
37
37
  // src/scanner.ts
@@ -866,20 +866,50 @@ function scan(code, language) {
866
866
  }
867
867
 
868
868
  // src/salt.ts
869
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
870
- import { join } from "path";
869
+ import { readFileSync, writeFileSync, mkdirSync, existsSync as existsSync2, renameSync as renameSync2 } from "fs";
870
+ import { join as join2 } from "path";
871
871
  import { homedir } from "os";
872
872
  import { randomBytes } from "crypto";
873
+
874
+ // src/config-dir.ts
875
+ import { existsSync, renameSync } from "fs";
876
+ import { join } from "path";
877
+ var PROJECT_CONFIG_DIR_NAME = ".pretest";
878
+ var LEGACY_PROJECT_CONFIG_DIR_NAME = ".pretense";
879
+ function migrateLegacyProjectConfigDir(parentDir) {
880
+ const next = join(parentDir, PROJECT_CONFIG_DIR_NAME);
881
+ const prev = join(parentDir, LEGACY_PROJECT_CONFIG_DIR_NAME);
882
+ if (existsSync(next)) return;
883
+ if (!existsSync(prev)) return;
884
+ try {
885
+ renameSync(prev, next);
886
+ } catch {
887
+ }
888
+ }
889
+
890
+ // src/salt.ts
873
891
  var SALT_BYTES = 32;
874
892
  function getSaltPath() {
875
- const dir = join(homedir(), ".pretense");
876
- return { dir, path: join(dir, "mutation.salt") };
893
+ const home = homedir();
894
+ migrateLegacyProjectConfigDir(home);
895
+ const dir = join2(home, PROJECT_CONFIG_DIR_NAME);
896
+ const legacyDir = join2(home, LEGACY_PROJECT_CONFIG_DIR_NAME);
897
+ const path = join2(dir, "mutation.salt");
898
+ const legacySalt = join2(legacyDir, "mutation.salt");
899
+ if (!existsSync2(path) && existsSync2(legacySalt)) {
900
+ try {
901
+ if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
902
+ renameSync2(legacySalt, path);
903
+ } catch {
904
+ }
905
+ }
906
+ return { dir, path };
877
907
  }
878
908
  var _cachedSalt = null;
879
909
  function getMutationSalt() {
880
910
  if (_cachedSalt) return _cachedSalt;
881
911
  const { dir, path } = getSaltPath();
882
- if (existsSync(path)) {
912
+ if (existsSync2(path)) {
883
913
  try {
884
914
  const raw = readFileSync(path, "utf-8").trim();
885
915
  if (/^[0-9a-f]{64}$/i.test(raw)) {
@@ -901,6 +931,12 @@ function getMutationSalt() {
901
931
  function buildSaltedSeed(baseSeed) {
902
932
  return `${baseSeed}:${getMutationSalt()}`;
903
933
  }
934
+ function effectiveSeedForMutation(userSeed) {
935
+ if (userSeed === "pretense" || userSeed === "pretest") {
936
+ return buildSaltedSeed("pretense");
937
+ }
938
+ return userSeed;
939
+ }
904
940
 
905
941
  // src/deterministic-id.ts
906
942
  function hash32(str) {
@@ -944,7 +980,7 @@ function prefixForType(type) {
944
980
  return "_tok";
945
981
  }
946
982
  }
947
- function mutate(code, language, seed = "pretense") {
983
+ function mutate(code, language, seed = "pretest") {
948
984
  const startMs = performance.now();
949
985
  const lang = language ?? detectLanguage(code);
950
986
  if (!code || !code.trim()) {
@@ -955,7 +991,7 @@ function mutate(code, language, seed = "pretense") {
955
991
  stats: { tokensScanned: 0, tokensMutated: 0, durationMs: 0, language: lang }
956
992
  };
957
993
  }
958
- const effectiveSeed = seed === "pretense" ? buildSaltedSeed(seed) : seed;
994
+ const effectiveSeed = effectiveSeedForMutation(seed);
959
995
  const { tokens } = scan(code, lang);
960
996
  const map = /* @__PURE__ */ new Map();
961
997
  for (const token of tokens) {
@@ -1044,7 +1080,7 @@ function reverse(mutatedCode, map, secretsMap) {
1044
1080
  // src/secrets.ts
1045
1081
  var SECRET_PATTERNS = [
1046
1082
  { name: "anthropic-api-key", category: "secret", severity: "critical", defaultAction: "block", pattern: /sk-ant-api\d{2}-[A-Za-z0-9_-]{40,}/g },
1047
- /** Legacy `sk-…` and modern `sk-proj-…` (hyphenated body); aligned with @pretense/scanner */
1083
+ /** Legacy `sk-…` and modern `sk-proj-…` (hyphenated body); aligned with upstream scanner heuristics */
1048
1084
  { name: "openai-api-key", category: "secret", severity: "critical", defaultAction: "block", pattern: /sk-(?:proj-)?[A-Za-z0-9_-]{20,}/g },
1049
1085
  { name: "aws-access-key", category: "secret", severity: "critical", defaultAction: "block", pattern: /AKIA[0-9A-Z]{16}/g },
1050
1086
  /** `AWS_SECRET = '…40 chars…'` (not `AWS_SECRET_ACCESS_KEY`, which is covered below). */
@@ -1307,7 +1343,7 @@ function applyRedactionsTracked(text, matches, mutationSeed = buildSaltedSeed("p
1307
1343
  }
1308
1344
 
1309
1345
  // src/store.ts
1310
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
1346
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync3 } from "fs";
1311
1347
  import { dirname } from "path";
1312
1348
  var MutationStore = class {
1313
1349
  entries = /* @__PURE__ */ new Map();
@@ -1372,7 +1408,7 @@ var MutationStore = class {
1372
1408
  */
1373
1409
  persist() {
1374
1410
  const dir = dirname(this.filePath);
1375
- if (!existsSync2(dir)) {
1411
+ if (!existsSync3(dir)) {
1376
1412
  mkdirSync2(dir, { recursive: true });
1377
1413
  }
1378
1414
  const data = JSON.stringify([...this.entries.values()], null, 2);
@@ -1383,7 +1419,7 @@ var MutationStore = class {
1383
1419
  * No-ops if the file doesn't exist.
1384
1420
  */
1385
1421
  load() {
1386
- if (!existsSync2(this.filePath)) return;
1422
+ if (!existsSync3(this.filePath)) return;
1387
1423
  try {
1388
1424
  const raw = readFileSync2(this.filePath, "utf-8");
1389
1425
  const parsed = JSON.parse(raw);
@@ -1418,41 +1454,42 @@ var MutationStore = class {
1418
1454
  };
1419
1455
 
1420
1456
  // src/config.ts
1421
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1422
- import { join as join2, resolve } from "path";
1457
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1458
+ import { join as join3, resolve } from "path";
1423
1459
  import { createHmac } from "crypto";
1424
- var CONFIG_DIR_NAME = ".pretense";
1460
+ var CONFIG_DIR_NAME = PROJECT_CONFIG_DIR_NAME;
1425
1461
  var CONFIG_FILE = "config.json";
1426
1462
  var MUTATION_MAP_FILE = "mutation-map.json";
1427
1463
  var AUDIT_LOG_FILE = "audit.log";
1428
1464
  var USAGE_FILE = "usage.json";
1429
1465
  function getConfigDir(baseDir) {
1430
1466
  const base = baseDir ?? process.cwd();
1467
+ migrateLegacyProjectConfigDir(base);
1431
1468
  return resolve(base, CONFIG_DIR_NAME);
1432
1469
  }
1433
1470
  function initConfig(dir) {
1434
1471
  const configDir = getConfigDir(dir);
1435
- if (!existsSync3(configDir)) {
1472
+ if (!existsSync4(configDir)) {
1436
1473
  mkdirSync3(configDir, { recursive: true });
1437
1474
  }
1438
- const configPath = join2(configDir, CONFIG_FILE);
1439
- if (!existsSync3(configPath)) {
1475
+ const configPath = join3(configDir, CONFIG_FILE);
1476
+ if (!existsSync4(configPath)) {
1440
1477
  const config = {
1441
1478
  ...DEFAULT_CONFIG,
1442
1479
  storePath: configDir
1443
1480
  };
1444
1481
  writeFileSync3(configPath, JSON.stringify(config, null, 2), "utf-8");
1445
1482
  }
1446
- const mapPath = join2(configDir, MUTATION_MAP_FILE);
1447
- if (!existsSync3(mapPath)) {
1483
+ const mapPath = join3(configDir, MUTATION_MAP_FILE);
1484
+ if (!existsSync4(mapPath)) {
1448
1485
  writeFileSync3(mapPath, "[]", "utf-8");
1449
1486
  }
1450
- const auditPath = join2(configDir, AUDIT_LOG_FILE);
1451
- if (!existsSync3(auditPath)) {
1487
+ const auditPath = join3(configDir, AUDIT_LOG_FILE);
1488
+ if (!existsSync4(auditPath)) {
1452
1489
  writeFileSync3(auditPath, "", "utf-8");
1453
1490
  }
1454
- const usagePath = join2(configDir, USAGE_FILE);
1455
- if (!existsSync3(usagePath)) {
1491
+ const usagePath = join3(configDir, USAGE_FILE);
1492
+ if (!existsSync4(usagePath)) {
1456
1493
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1457
1494
  const month = today.slice(0, 7);
1458
1495
  const usageData = { month, mutations: 0, firstUseDate: today };
@@ -1466,8 +1503,8 @@ function initConfig(dir) {
1466
1503
  }
1467
1504
  function loadConfig(dir) {
1468
1505
  const configDir = getConfigDir(dir);
1469
- const configPath = join2(configDir, CONFIG_FILE);
1470
- if (!existsSync3(configPath)) {
1506
+ const configPath = join3(configDir, CONFIG_FILE);
1507
+ if (!existsSync4(configPath)) {
1471
1508
  return { ...DEFAULT_CONFIG };
1472
1509
  }
1473
1510
  try {
@@ -1480,7 +1517,7 @@ function loadConfig(dir) {
1480
1517
  }
1481
1518
  var USAGE_HMAC_SECRET = "pretense_usage_integrity_v1";
1482
1519
  function getUsageSecret() {
1483
- return process.env["PRETENSE_USAGE_SECRET"] ?? USAGE_HMAC_SECRET;
1520
+ return process.env["PRETEST_USAGE_SECRET"]?.trim() || process.env["PRETENSE_USAGE_SECRET"]?.trim() || USAGE_HMAC_SECRET;
1484
1521
  }
1485
1522
  function computeUsageChecksum(data) {
1486
1523
  const payload = JSON.stringify({ month: data.month, mutations: data.mutations, firstUseDate: data.firstUseDate });
@@ -1492,10 +1529,10 @@ function verifyUsageChecksum(data) {
1492
1529
  }
1493
1530
  function loadUsage(dir) {
1494
1531
  const configDir = getConfigDir(dir);
1495
- const usagePath = join2(configDir, USAGE_FILE);
1532
+ const usagePath = join3(configDir, USAGE_FILE);
1496
1533
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
1497
1534
  const currentMonth = today.slice(0, 7);
1498
- if (!existsSync3(usagePath)) {
1535
+ if (!existsSync4(usagePath)) {
1499
1536
  return { month: currentMonth, mutations: 0, firstUseDate: today };
1500
1537
  }
1501
1538
  try {
@@ -1506,7 +1543,7 @@ function loadUsage(dir) {
1506
1543
  return { month: currentMonth, mutations: 0, firstUseDate: data.firstUseDate ?? legacyDate };
1507
1544
  }
1508
1545
  if (!verifyUsageChecksum({ month: data.month, mutations: data.mutations, firstUseDate: data.firstUseDate, checksum: data.checksum })) {
1509
- process.stderr.write("[PRETENSE] Warning: usage.json integrity check failed. Resetting usage counter.\n");
1546
+ process.stderr.write("[PRETEST] Warning: usage.json integrity check failed. Resetting usage counter.\n");
1510
1547
  return { month: currentMonth, mutations: 0, firstUseDate: data.firstUseDate ?? today };
1511
1548
  }
1512
1549
  if (data.month !== currentMonth) {
@@ -1519,10 +1556,10 @@ function loadUsage(dir) {
1519
1556
  }
1520
1557
  function saveUsage(usage, dir) {
1521
1558
  const configDir = getConfigDir(dir);
1522
- if (!existsSync3(configDir)) {
1559
+ if (!existsSync4(configDir)) {
1523
1560
  mkdirSync3(configDir, { recursive: true });
1524
1561
  }
1525
- const usagePath = join2(configDir, USAGE_FILE);
1562
+ const usagePath = join3(configDir, USAGE_FILE);
1526
1563
  const checksum = computeUsageChecksum(usage);
1527
1564
  writeFileSync3(usagePath, JSON.stringify({ ...usage, checksum }, null, 2), "utf-8");
1528
1565
  }
@@ -1531,7 +1568,7 @@ var LICENSE_PAYLOAD_REGEX = /^[a-zA-Z0-9]+$/;
1531
1568
  function isValidLicenseKey(key, prefix) {
1532
1569
  if (key.length < MIN_LICENSE_KEY_LENGTH) return false;
1533
1570
  const afterPrefix = key.slice(prefix.length);
1534
- const hmacSecret = process.env["PRETENSE_LICENSE_SECRET"];
1571
+ const hmacSecret = process.env["PRETEST_LICENSE_SECRET"]?.trim() || process.env["PRETENSE_LICENSE_SECRET"]?.trim();
1535
1572
  if (hmacSecret) {
1536
1573
  const lastUnderscore = afterPrefix.lastIndexOf("_");
1537
1574
  if (lastUnderscore === -1) return false;
@@ -1545,7 +1582,7 @@ function isValidLicenseKey(key, prefix) {
1545
1582
  return LICENSE_PAYLOAD_REGEX.test(afterPrefix);
1546
1583
  }
1547
1584
  function detectTier() {
1548
- const key = process.env["PRETENSE_LICENSE_KEY"] ?? "";
1585
+ const key = process.env["PRETEST_LICENSE_KEY"]?.trim() || process.env["PRETENSE_LICENSE_KEY"]?.trim() || "";
1549
1586
  if (key.startsWith("pre_ent_") && isValidLicenseKey(key, "pre_ent_")) return "enterprise";
1550
1587
  if (key.startsWith("pre_pro_") && isValidLicenseKey(key, "pre_pro_")) return "pro";
1551
1588
  return "free";
@@ -1568,13 +1605,13 @@ function getTierLimits(tier) {
1568
1605
  }
1569
1606
 
1570
1607
  // src/audit.ts
1571
- import { appendFileSync, existsSync as existsSync4, readFileSync as readFileSync4, mkdirSync as mkdirSync4 } from "fs";
1572
- import { join as join3, dirname as dirname2 } from "path";
1608
+ import { appendFileSync, existsSync as existsSync5, readFileSync as readFileSync4, mkdirSync as mkdirSync4 } from "fs";
1609
+ import { join as join4, dirname as dirname2 } from "path";
1573
1610
  function writeAuditEntry(entry, dir) {
1574
1611
  const configDir = getConfigDir(dir);
1575
- const auditPath = join3(configDir, "audit.log");
1612
+ const auditPath = join4(configDir, "audit.log");
1576
1613
  const logDir = dirname2(auditPath);
1577
- if (!existsSync4(logDir)) {
1614
+ if (!existsSync5(logDir)) {
1578
1615
  mkdirSync4(logDir, { recursive: true });
1579
1616
  }
1580
1617
  const line = JSON.stringify(entry) + "\n";
@@ -1594,8 +1631,8 @@ function createAuditEntry(sessionId, file, identifiersMutated, secretsBlocked, l
1594
1631
  function readAuditLog(options = {}) {
1595
1632
  const { limit, dir } = options;
1596
1633
  const configDir = getConfigDir(dir);
1597
- const auditPath = join3(configDir, "audit.log");
1598
- if (!existsSync4(auditPath)) {
1634
+ const auditPath = join4(configDir, "audit.log");
1635
+ if (!existsSync5(auditPath)) {
1599
1636
  return [];
1600
1637
  }
1601
1638
  const raw = readFileSync4(auditPath, "utf-8");
@@ -1662,7 +1699,7 @@ import { Hono } from "hono";
1662
1699
  import { serve } from "@hono/node-server";
1663
1700
  import { nanoid } from "nanoid";
1664
1701
  import { createServer } from "net";
1665
- import { existsSync as existsSync6, watch } from "fs";
1702
+ import { existsSync as existsSync7, watch } from "fs";
1666
1703
 
1667
1704
  // src/auth.ts
1668
1705
  import { createHash } from "crypto";
@@ -1782,18 +1819,55 @@ async function collectGitContextCached(cwd = process.cwd(), now = Date.now()) {
1782
1819
  }
1783
1820
 
1784
1821
  // src/commands/login.ts
1785
- import { existsSync as existsSync5, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4, readFileSync as readFileSync5, chmodSync, readSync } from "fs";
1786
- import { join as join4 } from "path";
1822
+ import { existsSync as existsSync6, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4, readFileSync as readFileSync5, chmodSync, readSync } from "fs";
1823
+ import { join as join5 } from "path";
1787
1824
  import { homedir as homedir2 } from "os";
1788
1825
  import readline from "readline/promises";
1789
1826
  import chalk from "chalk";
1790
- var CONFIG_DIR_NAME2 = ".pretense";
1827
+
1828
+ // src/dashboard-env.ts
1829
+ var DASHBOARD_API_KEY_ENVS = ["PRETEST_API_KEY", "PRETENSE_API_KEY"];
1830
+ var DASHBOARD_API_URL_ENVS = ["PRETEST_API_URL", "PRETENSE_API_URL"];
1831
+ var DASHBOARD_NO_BANNER_ENVS = ["PRETEST_NO_BANNER", "PRETENSE_NO_BANNER"];
1832
+ function firstNonEmptyEnv(names) {
1833
+ for (const name of names) {
1834
+ const v = process.env[name]?.trim();
1835
+ if (v) return v;
1836
+ }
1837
+ return "";
1838
+ }
1839
+ function activeDashboardApiKeyEnvName() {
1840
+ for (const name of DASHBOARD_API_KEY_ENVS) {
1841
+ const v = process.env[name]?.trim();
1842
+ if (v) return name;
1843
+ }
1844
+ return null;
1845
+ }
1846
+ function assignDashboardApiKeyToProcess(key) {
1847
+ process.env["PRETEST_API_KEY"] = key;
1848
+ process.env["PRETENSE_API_KEY"] = key;
1849
+ }
1850
+ function clearDashboardApiKeyFromProcess() {
1851
+ delete process.env["PRETEST_API_KEY"];
1852
+ delete process.env["PRETENSE_API_KEY"];
1853
+ }
1854
+ function hasDashboardApiKeyInEnv() {
1855
+ return DASHBOARD_API_KEY_ENVS.some((n) => !!process.env[n]?.trim());
1856
+ }
1857
+
1858
+ // src/publish-info.ts
1859
+ var PUBLISH_PACKAGE_URL = "https://www.npmjs.com/package/@blockyfy/stg-cli";
1860
+
1861
+ // src/commands/login.ts
1862
+ var CONFIG_DIR_NAME2 = PROJECT_CONFIG_DIR_NAME;
1791
1863
  var CONFIG_FILE2 = "config.json";
1792
1864
  function getUserDashboardConfigDir() {
1793
- return join4(homedir2(), CONFIG_DIR_NAME2);
1865
+ const home = homedir2();
1866
+ migrateLegacyProjectConfigDir(home);
1867
+ return join5(home, CONFIG_DIR_NAME2);
1794
1868
  }
1795
1869
  function getUserDashboardConfigPath() {
1796
- return join4(getUserDashboardConfigDir(), CONFIG_FILE2);
1870
+ return join5(getUserDashboardConfigDir(), CONFIG_FILE2);
1797
1871
  }
1798
1872
  function isValidKeyShape(key) {
1799
1873
  const trimmed = key.trim();
@@ -1826,29 +1900,30 @@ function maskKey(key) {
1826
1900
  return `${trimmed.slice(0, 12)}${"\u2022".repeat(8)}${trimmed.slice(-4)}`;
1827
1901
  }
1828
1902
  function logDashboardCredentialHint() {
1829
- const env = process.env["PRETENSE_API_KEY"]?.trim() ?? "";
1903
+ const envName = activeDashboardApiKeyEnvName();
1904
+ const env = envName ? process.env[envName]?.trim() ?? "" : "";
1830
1905
  const envOk = env.length > 0 && isValidKeyShape(env);
1831
1906
  const abs = getUserDashboardConfigPath();
1832
1907
  const fk = loadApiKey();
1833
- if (envOk) {
1908
+ if (envOk && envName) {
1834
1909
  console.error(
1835
1910
  chalk.gray(
1836
- `[pretense] Dashboard key source: PRETENSE_API_KEY in environment (${maskKey(env)}) \u2014 unset this variable after logout if you expect no key.`
1911
+ `[pretest] Dashboard key source: ${envName} in environment (${maskKey(env)}) \u2014 unset this variable after logout if you expect no key.`
1837
1912
  )
1838
1913
  );
1839
1914
  } else if (fk && isValidKeyShape(fk)) {
1840
- console.error(chalk.gray(`[pretense] Dashboard key source: ${abs} (${maskKey(fk)})`));
1915
+ console.error(chalk.gray(`[pretest] Dashboard key source: ${abs} (${maskKey(fk)})`));
1841
1916
  } else {
1842
- console.error(chalk.gray("[pretense] Dashboard key source: none configured."));
1917
+ console.error(chalk.gray("[pretest] Dashboard key source: none configured."));
1843
1918
  }
1844
1919
  }
1845
1920
  function saveApiKey(key, configDir = getUserDashboardConfigDir()) {
1846
- if (!existsSync5(configDir)) {
1921
+ if (!existsSync6(configDir)) {
1847
1922
  mkdirSync5(configDir, { recursive: true });
1848
1923
  }
1849
- const path = join4(configDir, CONFIG_FILE2);
1924
+ const path = join5(configDir, CONFIG_FILE2);
1850
1925
  let existing = {};
1851
- if (existsSync5(path)) {
1926
+ if (existsSync6(path)) {
1852
1927
  try {
1853
1928
  existing = JSON.parse(readFileSync5(path, "utf-8"));
1854
1929
  } catch {
@@ -1868,8 +1943,8 @@ function saveApiKey(key, configDir = getUserDashboardConfigDir()) {
1868
1943
  return path;
1869
1944
  }
1870
1945
  function removeSavedDashboardCredentials(configDir = getUserDashboardConfigDir()) {
1871
- const path = join4(configDir, CONFIG_FILE2);
1872
- if (!existsSync5(path)) return { removed: false, path };
1946
+ const path = join5(configDir, CONFIG_FILE2);
1947
+ if (!existsSync6(path)) return { removed: false, path };
1873
1948
  let existing = {};
1874
1949
  try {
1875
1950
  existing = JSON.parse(readFileSync5(path, "utf-8"));
@@ -1889,8 +1964,8 @@ function removeSavedDashboardCredentials(configDir = getUserDashboardConfigDir()
1889
1964
  return { removed: true, path };
1890
1965
  }
1891
1966
  function loadApiKey(configDir = getUserDashboardConfigDir()) {
1892
- const path = join4(configDir, CONFIG_FILE2);
1893
- if (!existsSync5(path)) return null;
1967
+ const path = join5(configDir, CONFIG_FILE2);
1968
+ if (!existsSync6(path)) return null;
1894
1969
  try {
1895
1970
  const raw = readFileSync5(path, "utf-8");
1896
1971
  const parsed = JSON.parse(raw);
@@ -1903,7 +1978,7 @@ function loadApiKey(configDir = getUserDashboardConfigDir()) {
1903
1978
  return null;
1904
1979
  }
1905
1980
  function resolveDashboardKeyCandidate() {
1906
- const env = (process.env["PRETENSE_API_KEY"] ?? "").trim();
1981
+ const env = firstNonEmptyEnv(DASHBOARD_API_KEY_ENVS);
1907
1982
  if (env.length > 0) {
1908
1983
  if (!isValidKeyShape(env)) {
1909
1984
  return { key: null, fromFile: false, badEnv: true };
@@ -1919,14 +1994,14 @@ function resolveDashboardKeyCandidate() {
1919
1994
  function installDashboardKeyForCurrentProcess(key) {
1920
1995
  const trimmed = key.trim();
1921
1996
  const path = saveApiKey(trimmed);
1922
- process.env["PRETENSE_API_KEY"] = trimmed;
1997
+ assignDashboardApiKeyToProcess(trimmed);
1923
1998
  return path;
1924
1999
  }
1925
2000
  async function promptDashboardApiKeyAfterFailure() {
1926
2001
  if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
1927
2002
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1928
2003
  try {
1929
- const line = (await rl.question(chalk.bold("Pretense dashboard API key: "))).trim();
2004
+ const line = (await rl.question(chalk.bold("Dashboard API key: "))).trim();
1930
2005
  return line.length > 0 ? line : null;
1931
2006
  } finally {
1932
2007
  rl.close();
@@ -1935,9 +2010,15 @@ async function promptDashboardApiKeyAfterFailure() {
1935
2010
  async function ensureDashboardKeyForStart() {
1936
2011
  const { key, fromFile, badEnv } = resolveDashboardKeyCandidate();
1937
2012
  if (badEnv) {
1938
- console.error(chalk.red("Error: PRETENSE_API_KEY is set but is not a valid Pretense dashboard API key shape."));
1939
2013
  console.error(
1940
- chalk.gray("Keys look like prtns_live_\u2026 or pk_live_\u2026. Fix the variable or unset it to use ~/.pretense/config.json.")
2014
+ chalk.red(
2015
+ "Error: A dashboard API key is set in the environment but does not match the expected key shape."
2016
+ )
2017
+ );
2018
+ console.error(
2019
+ chalk.gray(
2020
+ "Keys look like prtns_live_\u2026 or pk_live_\u2026. Fix the variable or unset it to use ~/.pretest/config.json."
2021
+ )
1941
2022
  );
1942
2023
  process.exit(1);
1943
2024
  }
@@ -1947,32 +2028,34 @@ async function ensureDashboardKeyForStart() {
1947
2028
  if (fromFile) {
1948
2029
  console.warn(
1949
2030
  chalk.yellow(
1950
- "Ignoring invalid `api_key` in ~/.pretense/config.json (wrong shape). Enter a new key or run `pretense login --key ...`."
2031
+ "Ignoring invalid `api_key` in ~/.pretest/config.json (wrong shape). Enter a new key or run `pretest login --key ...`."
1951
2032
  )
1952
2033
  );
1953
2034
  }
1954
2035
  const stdinOk = process.stdin.isTTY;
1955
2036
  const stdoutOk = process.stdout.isTTY;
1956
2037
  if (!stdinOk || !stdoutOk) {
1957
- console.error(chalk.red("Error: Pretense API key required to start the proxy."));
2038
+ console.error(chalk.red("Error: Dashboard API key required to start the proxy."));
1958
2039
  console.error(
1959
- chalk.gray(
1960
- "Save one with `pretense login --key prtns_live_...` or set PRETENSE_API_KEY."
1961
- )
2040
+ chalk.gray("Save one with `pretest login --key prtns_live_...` or set PRETEST_API_KEY.")
1962
2041
  );
1963
2042
  process.exit(1);
1964
2043
  }
1965
2044
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1966
2045
  try {
1967
- console.log(chalk.cyan("No Pretense API key found in ~/.pretense/config.json or $PRETENSE_API_KEY."));
1968
- const entered = (await rl.question(chalk.bold("Enter your Pretense API key: "))).trim();
2046
+ console.log(
2047
+ chalk.cyan(
2048
+ "No dashboard API key found in ~/.pretest/config.json. Set PRETEST_API_KEY or run pretest login."
2049
+ )
2050
+ );
2051
+ const entered = (await rl.question(chalk.bold("Enter your dashboard API key: "))).trim();
1969
2052
  if (!entered) {
1970
2053
  console.error(chalk.red("No key entered; exiting."));
1971
2054
  process.exit(1);
1972
2055
  }
1973
2056
  if (!isValidKeyShape(entered)) {
1974
- console.error(chalk.red("That does not look like a Pretense API key (expect prtns_live_\u2026 or pk_live_\u2026)."));
1975
- console.error(chalk.gray("Get one from your Pretense dashboard, then run `pretense login --key ...`."));
2057
+ console.error(chalk.red("That does not look like a dashboard API key (expect prtns_live_\u2026 or pk_live_\u2026)."));
2058
+ console.error(chalk.gray(`Get a key via the package page, then run \`pretest login --key ...\`: ${PUBLISH_PACKAGE_URL}`));
1976
2059
  process.exit(1);
1977
2060
  }
1978
2061
  const path = installDashboardKeyForCurrentProcess(entered);
@@ -1983,29 +2066,29 @@ async function ensureDashboardKeyForStart() {
1983
2066
  }
1984
2067
  const persisted = resolveDashboardKeyCandidate();
1985
2068
  if (!persisted.key || persisted.badEnv) {
1986
- console.error(chalk.red("Error: Pretense dashboard API key could not be confirmed after login prompt."));
2069
+ console.error(chalk.red("Error: Dashboard API key could not be confirmed after login prompt."));
1987
2070
  process.exit(1);
1988
2071
  }
1989
2072
  }
1990
2073
  function runLogin(opts = {}) {
1991
- const candidate = opts.key?.trim() || (process.env["PRETENSE_API_KEY"] ?? "").trim() || readStdinIfPiped();
2074
+ const candidate = opts.key?.trim() || firstNonEmptyEnv(DASHBOARD_API_KEY_ENVS) || readStdinIfPiped();
1992
2075
  if (!candidate) {
1993
2076
  console.error(chalk.red("Error: no API key provided."));
1994
2077
  console.error(
1995
- chalk.gray("Try: pretense login --key pk_live_xxxxx")
2078
+ chalk.gray("Try: pretest login --key pk_live_xxxxx")
1996
2079
  );
1997
2080
  console.error(
1998
- chalk.gray(" or: echo $PRETENSE_API_KEY | pretense login")
2081
+ chalk.gray(" or: echo $PRETEST_API_KEY | pretest login")
1999
2082
  );
2000
2083
  return 1;
2001
2084
  }
2002
2085
  if (!isValidKeyShape(candidate)) {
2003
- console.error(chalk.red("Error: that does not look like a Pretense API key."));
2086
+ console.error(chalk.red("Error: that does not look like a dashboard API key."));
2004
2087
  console.error(
2005
2088
  chalk.gray("Keys start with prtns_live_ (or pk_live_) and are at least 24 characters long.")
2006
2089
  );
2007
2090
  console.error(
2008
- chalk.gray("Get one at https://pretense.ai/dashboard/settings/api-keys")
2091
+ chalk.gray(`See: ${PUBLISH_PACKAGE_URL}`)
2009
2092
  );
2010
2093
  return 1;
2011
2094
  }
@@ -2030,10 +2113,10 @@ function usageSummaryFromValidate(v) {
2030
2113
  keyStatus: "active"
2031
2114
  };
2032
2115
  }
2033
- var DEFAULT_PRETENSE_API_URL = "https://api.pretense.ai";
2116
+ var DEFAULT_PRETENSE_API_URL = "https://pretense-stg-api.nxtsen.com";
2034
2117
  var DEFAULT_REQUEST_TIMEOUT_MS = 15e3;
2035
2118
  function getConfiguredApiRoot(rootOverride) {
2036
- const raw = (rootOverride ?? process.env["PRETENSE_API_URL"] ?? DEFAULT_PRETENSE_API_URL).trim();
2119
+ const raw = (rootOverride?.trim() || firstNonEmptyEnv(DASHBOARD_API_URL_ENVS) || DEFAULT_PRETENSE_API_URL).trim();
2037
2120
  if (!raw) {
2038
2121
  return DEFAULT_PRETENSE_API_URL.replace(/\/$/, "");
2039
2122
  }
@@ -2043,7 +2126,7 @@ function getConfiguredApiRoot(rootOverride) {
2043
2126
  }
2044
2127
  try {
2045
2128
  const u = new URL(normalized);
2046
- const origin = /^pretense\.ai$/i.test(u.hostname) ? "https://api.pretense.ai" : u.origin;
2129
+ const origin = /^pretense\.ai$/i.test(u.hostname) ? DEFAULT_PRETENSE_API_URL.replace(/\/$/, "") : u.origin;
2047
2130
  const path = u.pathname === "/" ? "" : u.pathname.replace(/\/$/, "");
2048
2131
  return `${origin}${path}`;
2049
2132
  } catch {
@@ -2056,20 +2139,20 @@ function getCliApiUrl(pathWithinCli, rootOverride) {
2056
2139
  return `${root}/api/cli/${tail}`;
2057
2140
  }
2058
2141
  function getApiRequestTimeoutMs() {
2059
- const raw = process.env["PRETENSE_API_TIMEOUT_MS"]?.trim();
2142
+ const raw = process.env["PRETEST_API_TIMEOUT_MS"]?.trim() || process.env["PRETENSE_API_TIMEOUT_MS"]?.trim();
2060
2143
  if (!raw || !/^\d+$/.test(raw)) return DEFAULT_REQUEST_TIMEOUT_MS;
2061
2144
  const n = parseInt(raw, 10);
2062
2145
  return Math.min(Math.max(n, 3e3), 12e4);
2063
2146
  }
2064
2147
  function getApiKey() {
2065
- const fromEnv = process.env["PRETENSE_API_KEY"]?.trim();
2148
+ const fromEnv = firstNonEmptyEnv(DASHBOARD_API_KEY_ENVS);
2066
2149
  if (fromEnv) return fromEnv;
2067
2150
  const fromFile = loadApiKey();
2068
2151
  if (!fromFile) return null;
2069
2152
  const t = fromFile.trim();
2070
2153
  return t.length > 0 ? t : null;
2071
2154
  }
2072
- function getPretenseApiKey() {
2155
+ function getDashboardApiKey() {
2073
2156
  return getApiKey();
2074
2157
  }
2075
2158
  var cachedValidation = null;
@@ -2109,7 +2192,7 @@ async function validateKey(opts = {}) {
2109
2192
  const apiKey = getApiKey();
2110
2193
  if (!apiKey) {
2111
2194
  if (enforceReachability) {
2112
- const err = new Error("Missing Pretense dashboard API key");
2195
+ const err = new Error("Missing dashboard API key");
2113
2196
  err.code = "MISSING_API_KEY";
2114
2197
  cachedValidation = null;
2115
2198
  lastValidationSuccessAt = 0;
@@ -2139,7 +2222,7 @@ async function validateKey(opts = {}) {
2139
2222
  throw err;
2140
2223
  }
2141
2224
  if (!resp.ok) {
2142
- const msg = `Pretense API returned HTTP ${resp.status} from ${validateUrl}`;
2225
+ const msg = `Dashboard API returned HTTP ${resp.status} from ${validateUrl}`;
2143
2226
  if (enforceReachability) {
2144
2227
  cachedValidation = null;
2145
2228
  lastValidationSuccessAt = 0;
@@ -2176,14 +2259,14 @@ async function validateKey(opts = {}) {
2176
2259
  throw err;
2177
2260
  }
2178
2261
  if (enforceReachability) {
2179
- const msg = err.name === "AbortError" ? `Timed out after ${timeoutMs}ms reaching ${validateUrl} (raise PRETENSE_API_TIMEOUT_MS)` : `Cannot reach Pretense API at ${validateUrl}: ${err.message}`;
2262
+ const msg = err.name === "AbortError" ? `Timed out after ${timeoutMs}ms reaching ${validateUrl} (raise PRETEST_API_TIMEOUT_MS or PRETENSE_API_TIMEOUT_MS)` : `Cannot reach dashboard API at ${validateUrl}: ${err.message}`;
2180
2263
  cachedValidation = null;
2181
2264
  lastValidationSuccessAt = 0;
2182
2265
  throw makeBackendReachabilityError("BACKEND_UNAVAILABLE", msg);
2183
2266
  }
2184
2267
  if (opts.verbose) {
2185
2268
  process.stderr.write(
2186
- `[PRETENSE] Backend validation failed: ${err.message}
2269
+ `[PRETEST] Backend validation failed: ${err.message}
2187
2270
  `
2188
2271
  );
2189
2272
  }
@@ -2209,7 +2292,7 @@ async function fetchUsageSummary(opts = {}) {
2209
2292
  } catch (err) {
2210
2293
  if (opts.verbose) {
2211
2294
  process.stderr.write(
2212
- `[PRETENSE] Usage summary fetch failed: ${err.message}
2295
+ `[PRETEST] Usage summary fetch failed: ${err.message}
2213
2296
  `
2214
2297
  );
2215
2298
  }
@@ -2227,7 +2310,7 @@ async function isWithinLimits() {
2227
2310
  if (check.mutationsRemaining !== -1 && check.mutationsRemaining <= 0) {
2228
2311
  return {
2229
2312
  allowed: false,
2230
- reason: `Monthly mutation limit reached (${check.mutationsUsed}/${check.monthlyMutationLimit}). Upgrade at https://pretense.ai/pricing`
2313
+ reason: `Monthly mutation limit reached (${check.mutationsUsed}/${check.monthlyMutationLimit}). See ${PUBLISH_PACKAGE_URL}`
2231
2314
  };
2232
2315
  }
2233
2316
  return { allowed: true };
@@ -2262,13 +2345,13 @@ async function uploadLog(event, options) {
2262
2345
  signal: controller.signal
2263
2346
  });
2264
2347
  if (!resp.ok && verbose) {
2265
- process.stderr.write(`[PRETENSE] log upload HTTP ${resp.status}
2348
+ process.stderr.write(`[PRETEST] log upload HTTP ${resp.status}
2266
2349
  `);
2267
2350
  }
2268
2351
  } catch (err) {
2269
2352
  if (verbose) {
2270
2353
  const msg = err instanceof Error ? err.message : String(err);
2271
- process.stderr.write(`[PRETENSE] log upload failed: ${msg}
2354
+ process.stderr.write(`[PRETEST] log upload failed: ${msg}
2272
2355
  `);
2273
2356
  }
2274
2357
  } finally {
@@ -2282,13 +2365,18 @@ function printStartClientInstructions(port) {
2282
2365
  const host = `http://localhost:${port}`;
2283
2366
  console.log();
2284
2367
  console.log(chalk2.cyan.bold("\u2500\u2500 Client setup (environment variables) \u2500\u2500"));
2285
- console.log(chalk2.gray("Point the CLI at the Pretense backend API (optional if using default):"));
2368
+ console.log(chalk2.gray("Point the CLI at the backend API (optional if using default):"));
2286
2369
  console.log(
2287
- chalk2.white(`export PRETENSE_API_URL='https://api.pretense.ai'`)
2370
+ chalk2.white(`export PRETEST_API_URL='https://pretense-stg-api.nxtsen.com'`)
2288
2371
  );
2289
2372
  console.log();
2290
- console.log(chalk2.gray("Log in with your Pretense dashboard API key:"));
2291
- console.log(chalk2.white("pretense login --key your-pretense-api-key"));
2373
+ console.log(chalk2.gray("Log in with your dashboard API key:"));
2374
+ console.log(chalk2.white("pretest login --key your-dashboard-api-key"));
2375
+ console.log();
2376
+ console.log(
2377
+ chalk2.gray("Documentation:"),
2378
+ chalk2.cyan.underline(PUBLISH_PACKAGE_URL)
2379
+ );
2292
2380
  console.log();
2293
2381
  console.log(
2294
2382
  chalk2.gray("Set the LLM base URL for your provider (proxy below):")
@@ -2305,15 +2393,15 @@ function printStartClientInstructions(port) {
2305
2393
  console.log(chalk2.cyan.bold("\u2500\u2500 Stop & log out \u2500\u2500"));
2306
2394
  console.log(
2307
2395
  chalk2.gray(
2308
- "Stop the proxy: press Ctrl+C in the terminal where pretense start is running."
2396
+ "Stop the proxy: press Ctrl+C in the terminal where pretest start is running."
2309
2397
  )
2310
2398
  );
2311
2399
  console.log(
2312
2400
  chalk2.gray(
2313
- "Remove the saved Pretense dashboard key from ~/.pretense/config.json:"
2401
+ "Remove the saved dashboard key from ~/.pretest/config.json:"
2314
2402
  )
2315
2403
  );
2316
- console.log(chalk2.white("pretense logout"));
2404
+ console.log(chalk2.white("pretest logout"));
2317
2405
  console.log(
2318
2406
  chalk2.gray(
2319
2407
  "(confirm with y / cancel with n.) Mutations stop immediately unless this proxy was started with"
@@ -2321,7 +2409,7 @@ function printStartClientInstructions(port) {
2321
2409
  );
2322
2410
  console.log(
2323
2411
  chalk2.gray(
2324
- "PRETENSE_API_KEY set in that same terminal \u2014 then press Ctrl+C and run pretense start again."
2412
+ "PRETEST_API_KEY in that same terminal \u2014 then press Ctrl+C and run pretest start again."
2325
2413
  )
2326
2414
  );
2327
2415
  console.log();
@@ -2354,11 +2442,11 @@ function attachDashboardLogoutWatcher(enabled) {
2354
2442
  if (!fk) {
2355
2443
  if (dashboardSavedCredentialsRevoked) return;
2356
2444
  dashboardSavedCredentialsRevoked = true;
2357
- delete process.env["PRETENSE_API_KEY"];
2445
+ clearDashboardApiKeyFromProcess();
2358
2446
  clearValidationCache();
2359
2447
  try {
2360
2448
  process.stderr.write(
2361
- `\x1B[33m[PRETENSE] Saved dashboard API key removed (~/.pretense/config.json, e.g. pretense logout). LLM proxy POST requests are disabled until you run pretense login and restart pretense start.\x1B[0m
2449
+ `\x1B[33m[PRETEST] Saved dashboard API key removed (~/.pretest/config.json, e.g. pretest logout). LLM proxy POST requests are disabled until you run pretest login and restart pretest start.\x1B[0m
2362
2450
  `
2363
2451
  );
2364
2452
  } catch {
@@ -2375,7 +2463,7 @@ function attachDashboardLogoutWatcher(enabled) {
2375
2463
  debounceTimer = setTimeout(applyFilesystemCredentialState, 120);
2376
2464
  };
2377
2465
  try {
2378
- if (!existsSync6(dir)) return;
2466
+ if (!existsSync7(dir)) return;
2379
2467
  watch(dir, () => {
2380
2468
  schedule();
2381
2469
  });
@@ -2484,8 +2572,8 @@ function daysSinceFirstUse() {
2484
2572
  function printUpgradeNudge(reason) {
2485
2573
  process.stdout.write(
2486
2574
  `
2487
- \x1B[33m[PRETENSE] ${reason}\x1B[0m
2488
- \x1B[33m[PRETENSE] Upgrade to Pro: https://pretense.ai/pricing\x1B[0m
2575
+ \x1B[33m[PRETEST] ${reason}\x1B[0m
2576
+ \x1B[33m[PRETEST] Upgrade to Pro: ${PUBLISH_PACKAGE_URL}\x1B[0m
2489
2577
 
2490
2578
  `
2491
2579
  );
@@ -2499,7 +2587,7 @@ function createProxy(opts = {}) {
2499
2587
  app.get(
2500
2588
  "/",
2501
2589
  (c) => c.json({
2502
- name: "pretense",
2590
+ name: "pretest",
2503
2591
  version: getCliSemver(),
2504
2592
  status: "running",
2505
2593
  routes: {
@@ -2510,7 +2598,7 @@ function createProxy(opts = {}) {
2510
2598
  "POST /*": "Proxy to upstream LLM API (Anthropic, OpenAI, Google auto-detected)"
2511
2599
  },
2512
2600
  languages: ["TypeScript", "JavaScript", "Python", "Go", "Java", "C#", "Ruby", "Rust"],
2513
- docs: "https://pretense.ai/docs"
2601
+ docs: PUBLISH_PACKAGE_URL
2514
2602
  })
2515
2603
  );
2516
2604
  app.get(
@@ -2569,19 +2657,19 @@ function createProxy(opts = {}) {
2569
2657
  {
2570
2658
  error: {
2571
2659
  type: "pretense_session_logged_out",
2572
- message: "Saved Pretense dashboard credentials were removed (for example pretense logout). Run pretense login, then restart pretense start. If you started the proxy with PRETENSE_API_KEY in this shell, stop it (Ctrl+C) and start again after logout."
2660
+ message: "Saved dashboard credentials were removed (for example pretest logout). Run pretest login, then restart pretest start. If you started the proxy with a dashboard API key in this shell, stop it (Ctrl+C) and start again after logout."
2573
2661
  }
2574
2662
  },
2575
2663
  401
2576
2664
  );
2577
2665
  }
2578
- const pretenseDashboardKey = getPretenseApiKey();
2579
- if (!pretenseDashboardKey) {
2666
+ const dashboardApiKey = getDashboardApiKey();
2667
+ if (!dashboardApiKey) {
2580
2668
  return c.json(
2581
2669
  {
2582
2670
  error: {
2583
2671
  type: "pretense_dashboard_key_required",
2584
- message: "Configure your Pretense dashboard API key: run `pretense login --key prtns_live_...` or set PRETENSE_API_KEY."
2672
+ message: "Configure your dashboard API key: run `pretest login --key prtns_live_...` or set PRETEST_API_KEY."
2585
2673
  }
2586
2674
  },
2587
2675
  401
@@ -2629,12 +2717,12 @@ function createProxy(opts = {}) {
2629
2717
  );
2630
2718
  const { monthlyMutations } = getTierLimits(tier);
2631
2719
  const usage = loadUsage();
2632
- if (tier === "free" && usage.mutations >= monthlyMutations) {
2720
+ if (!dashboardApiKey && tier === "free" && usage.mutations >= monthlyMutations) {
2633
2721
  return c.json(
2634
2722
  {
2635
2723
  error: {
2636
2724
  type: "pretense_rate_limit",
2637
- message: `Monthly mutation limit reached (${monthlyMutations}/month). Upgrade to Pro for unlimited: https://pretense.ai/pricing`
2725
+ message: `Monthly mutation limit reached (${monthlyMutations}/month). Upgrade to Pro for unlimited: ${PUBLISH_PACKAGE_URL}`
2638
2726
  }
2639
2727
  },
2640
2728
  429
@@ -2658,7 +2746,7 @@ function createProxy(opts = {}) {
2658
2746
  {
2659
2747
  error: {
2660
2748
  type: "pretense_forbidden",
2661
- message: "This API key is read-only. Create a read_write key in the dashboard to use the Pretense proxy."
2749
+ message: "This API key is read-only. Create a read_write key in the dashboard to use the Pretest proxy."
2662
2750
  }
2663
2751
  },
2664
2752
  403
@@ -2714,7 +2802,7 @@ function createProxy(opts = {}) {
2714
2802
  usage.mutations += tokensMutated;
2715
2803
  saveUsage(usage);
2716
2804
  const remoteLogDisabled = process.env["PRETENSE_DISABLE_REMOTE_LOG"] === "1";
2717
- if (pretenseDashboardKey && !remoteLogDisabled) {
2805
+ if (dashboardApiKey && !remoteLogDisabled) {
2718
2806
  void uploadLog(
2719
2807
  {
2720
2808
  file_count: 0,
@@ -2723,7 +2811,7 @@ function createProxy(opts = {}) {
2723
2811
  llm_provider: provider,
2724
2812
  cli_version: getCliSemver()
2725
2813
  },
2726
- { apiKey: pretenseDashboardKey, verbose }
2814
+ { apiKey: dashboardApiKey, verbose }
2727
2815
  );
2728
2816
  bumpCachedUsageAfterLog(tokensMutated);
2729
2817
  }
@@ -2732,7 +2820,7 @@ function createProxy(opts = {}) {
2732
2820
  printUpgradeNudge(`${usage.mutations}/${monthlyMutations} monthly mutations used. Running low!`);
2733
2821
  }
2734
2822
  if (tier === "free" && daysSinceFirstUse() >= 7) {
2735
- printUpgradeNudge("You've been using Pretense for 7+ days. Unlock Pro features: unlimited mutations, 90-day audit, Slack alerts.");
2823
+ printUpgradeNudge("You've been using Pretest for 7+ days. Unlock Pro features: unlimited mutations, 90-day audit, Slack alerts.");
2736
2824
  }
2737
2825
  const entry = {
2738
2826
  id: requestId,
@@ -2749,7 +2837,7 @@ function createProxy(opts = {}) {
2749
2837
  createAuditEntry(requestId, "proxy-request", tokensMutated, blockedSecrets.length, provider, latencyMs)
2750
2838
  );
2751
2839
  if (verbose && tokensMutated > 0) {
2752
- process.stdout.write(`[PRETENSE] ${tokensMutated} tokens mutated for request ${requestId}
2840
+ process.stdout.write(`[PRETEST] ${tokensMutated} tokens mutated for request ${requestId}
2753
2841
  `);
2754
2842
  }
2755
2843
  const headers = {};
@@ -2876,12 +2964,12 @@ function startProxy(opts = {}) {
2876
2964
  const requestedPort = opts.port ?? opts.config?.port ?? DEFAULT_CONFIG.port;
2877
2965
  const app = createProxy(opts);
2878
2966
  void (async () => {
2879
- const pretenseDashboardKeyFromEnvAtLaunch = !!process.env["PRETENSE_API_KEY"]?.trim();
2880
- const dashboardKey = getPretenseApiKey();
2967
+ const dashboardKeyFromEnvAtLaunch = hasDashboardApiKeyInEnv();
2968
+ const dashboardKey = getDashboardApiKey();
2881
2969
  if (!dashboardKey || !isValidKeyShape(dashboardKey)) {
2882
2970
  process.stderr.write(
2883
- `\x1B[31m[PRETENSE] API key required or invalid shape. Run \`pretense login --key prtns_live_...\`\x1B[0m
2884
- \x1B[31m[PRETENSE] or set PRETENSE_API_KEY. Get a key at https://pretense.ai/dashboard/settings/api-keys\x1B[0m
2971
+ `\x1B[31m[PRETEST] API key required or invalid shape. Run \`pretest login --key prtns_live_...\`\x1B[0m
2972
+ \x1B[31m[PRETEST] or set PRETEST_API_KEY. See ${PUBLISH_PACKAGE_URL}\x1B[0m
2885
2973
  `
2886
2974
  );
2887
2975
  process.exit(1);
@@ -2896,7 +2984,7 @@ function startProxy(opts = {}) {
2896
2984
  });
2897
2985
  if (!validation) {
2898
2986
  process.stderr.write(
2899
- `\x1B[31m[PRETENSE] Startup validation failed (no API key or unreachable backend). Cannot start proxy.\x1B[0m
2987
+ `\x1B[31m[PRETEST] Startup validation failed (no API key or unreachable backend). Cannot start proxy.\x1B[0m
2900
2988
  `
2901
2989
  );
2902
2990
  process.exit(1);
@@ -2904,7 +2992,7 @@ function startProxy(opts = {}) {
2904
2992
  const plan = validation.plan ?? "FREE";
2905
2993
  const remaining = validation.mutationsRemaining === -1 ? "unlimited" : String(validation.mutationsRemaining);
2906
2994
  process.stdout.write(
2907
- `\x1B[32m[PRETENSE] Key validated: ${plan} plan` + (validation.organizationName ? ` (${validation.organizationName})` : "") + ` \u2014 ${remaining} mutations remaining\x1B[0m
2995
+ `\x1B[32m[PRETEST] Key validated: ${plan} plan` + (validation.organizationName ? ` (${validation.organizationName})` : "") + ` \u2014 ${remaining} mutations remaining\x1B[0m
2908
2996
  `
2909
2997
  );
2910
2998
  break;
@@ -2912,62 +3000,62 @@ function startProxy(opts = {}) {
2912
3000
  const code = err.code;
2913
3001
  const msg = err.message;
2914
3002
  if (code === "BACKEND_UNAVAILABLE" || code === "AUTH_BACKEND_REJECTED") {
2915
- process.stderr.write(`\x1B[31m[PRETENSE] ${msg}\x1B[0m
3003
+ process.stderr.write(`\x1B[31m[PRETEST] ${msg}\x1B[0m
2916
3004
  `);
2917
- process.stderr.write(`\x1B[31m[PRETENSE] Fix network or set PRETENSE_API_URL if using a custom API.\x1B[0m
3005
+ process.stderr.write(`\x1B[31m[PRETEST] Fix network or set PRETEST_API_URL (or PRETENSE_API_URL) if using a custom API.\x1B[0m
2918
3006
  `);
2919
3007
  process.exit(1);
2920
3008
  }
2921
3009
  if (code === "ORG_INACTIVE") {
2922
- process.stderr.write(`\x1B[31m[PRETENSE] ${msg}\x1B[0m
3010
+ process.stderr.write(`\x1B[31m[PRETEST] ${msg}\x1B[0m
2923
3011
  `);
2924
- process.stderr.write(`\x1B[31m[PRETENSE] Your organization is inactive; contact support.\x1B[0m
3012
+ process.stderr.write(`\x1B[31m[PRETEST] Your organization is inactive; contact support.\x1B[0m
2925
3013
  `);
2926
3014
  process.exit(1);
2927
3015
  }
2928
3016
  const authRetryable = code === "INVALID_API_KEY" || code === "KEY_REVOKED" || code === "KEY_EXPIRED" || code === "AUTH_ERROR" || code === "MISSING_API_KEY";
2929
3017
  if (authRetryable && interactive) {
2930
- process.stderr.write(`\x1B[31m[PRETENSE] ${msg}\x1B[0m
3018
+ process.stderr.write(`\x1B[31m[PRETEST] ${msg}\x1B[0m
2931
3019
  `);
2932
3020
  process.stderr.write(
2933
- `\x1B[33m[PRETENSE] Enter your Pretense dashboard API key and press Enter (Ctrl+C to quit).\x1B[0m
3021
+ `\x1B[33m[PRETEST] Enter your dashboard API key and press Enter (Ctrl+C to quit).\x1B[0m
2934
3022
  `
2935
3023
  );
2936
3024
  let entered = null;
2937
3025
  for (; ; ) {
2938
3026
  entered = await promptDashboardApiKeyAfterFailure();
2939
3027
  if (!entered) {
2940
- process.stderr.write(`\x1B[31m[PRETENSE] No key entered; exiting.\x1B[0m
3028
+ process.stderr.write(`\x1B[31m[PRETEST] No key entered; exiting.\x1B[0m
2941
3029
  `);
2942
3030
  process.exit(1);
2943
3031
  }
2944
3032
  if (isValidKeyShape(entered)) break;
2945
3033
  process.stderr.write(
2946
- `\x1B[31m[PRETENSE] That does not look like a Pretense dashboard key (expect prtns_live_\u2026 or pk_live_\u2026).\x1B[0m
3034
+ `\x1B[31m[PRETEST] That does not look like a dashboard key (expect prtns_live_\u2026 or pk_live_\u2026).\x1B[0m
2947
3035
  `
2948
3036
  );
2949
3037
  }
2950
3038
  const savedPath = installDashboardKeyForCurrentProcess(entered);
2951
- process.stdout.write(`\x1B[32m[PRETENSE] Saved API key to ${savedPath}\x1B[0m
3039
+ process.stdout.write(`\x1B[32m[PRETEST] Saved API key to ${savedPath}\x1B[0m
2952
3040
  `);
2953
3041
  clearValidationCache();
2954
3042
  continue;
2955
3043
  }
2956
3044
  if (code === "KEY_REVOKED" || code === "KEY_EXPIRED" || code === "INVALID_API_KEY" || code === "AUTH_ERROR" || code === "MISSING_API_KEY") {
2957
- process.stderr.write(`\x1B[31m[PRETENSE] ${msg}\x1B[0m
3045
+ process.stderr.write(`\x1B[31m[PRETEST] ${msg}\x1B[0m
2958
3046
  `);
2959
- process.stderr.write(`\x1B[31m[PRETENSE] Run 'pretense login --key <new-key>' to fix.\x1B[0m
3047
+ process.stderr.write(`\x1B[31m[PRETEST] Run 'pretest login --key <new-key>' to fix.\x1B[0m
2960
3048
  `);
2961
3049
  process.exit(1);
2962
3050
  }
2963
- process.stderr.write(`\x1B[31m[PRETENSE] ${msg}\x1B[0m
3051
+ process.stderr.write(`\x1B[31m[PRETEST] ${msg}\x1B[0m
2964
3052
  `);
2965
- process.stderr.write(`\x1B[31m[PRETENSE] Run 'pretense login --key <new-key>' or check connectivity.\x1B[0m
3053
+ process.stderr.write(`\x1B[31m[PRETEST] Run 'pretest login --key <new-key>' or check connectivity.\x1B[0m
2966
3054
  `);
2967
3055
  process.exit(1);
2968
3056
  }
2969
3057
  }
2970
- attachDashboardLogoutWatcher(!pretenseDashboardKeyFromEnvAtLaunch);
3058
+ attachDashboardLogoutWatcher(!dashboardKeyFromEnvAtLaunch);
2971
3059
  const bannerTier = tierFromDashboardPlan(
2972
3060
  getCachedValidation()?.plan,
2973
3061
  detectTier()
@@ -2976,13 +3064,13 @@ function startProxy(opts = {}) {
2976
3064
  try {
2977
3065
  port = await findAvailablePort(requestedPort, 10);
2978
3066
  } catch (err) {
2979
- process.stderr.write(`\x1B[31m[PRETENSE] ${err.message}\x1B[0m
3067
+ process.stderr.write(`\x1B[31m[PRETEST] ${err.message}\x1B[0m
2980
3068
  `);
2981
3069
  process.exit(1);
2982
3070
  }
2983
3071
  if (port !== requestedPort) {
2984
3072
  process.stderr.write(
2985
- `\x1B[33m[PRETENSE] Port ${requestedPort} in use, falling back to ${port}.\x1B[0m
3073
+ `\x1B[33m[PRETEST] Port ${requestedPort} in use, falling back to ${port}.\x1B[0m
2986
3074
  `
2987
3075
  );
2988
3076
  }
@@ -2990,7 +3078,7 @@ function startProxy(opts = {}) {
2990
3078
  serve({ fetch: app.fetch, port }, () => {
2991
3079
  const portStr = String(port);
2992
3080
  process.stdout.write(`
2993
- \x1B[36mPretense v${getCliSemver()} [${bannerTier.toUpperCase()}]\x1B[0m
3081
+ \x1B[36mPretest v${getCliSemver()} [${bannerTier.toUpperCase()}]\x1B[0m
2994
3082
  Your code hits AI naked. We fix that.
2995
3083
 
2996
3084
  Proxy: http://localhost:${portStr}
@@ -3012,7 +3100,7 @@ function startProxy(opts = {}) {
3012
3100
  `);
3013
3101
  setInterval(() => {
3014
3102
  if (dashboardSavedCredentialsRevoked) return;
3015
- if (!getPretenseApiKey()) return;
3103
+ if (!getDashboardApiKey()) return;
3016
3104
  void validateKey({
3017
3105
  force: true,
3018
3106
  verbose: opts.verbose,
@@ -3068,13 +3156,13 @@ function printTokenFooter(filesScanned, mutationsMade) {
3068
3156
  if (tier === "free") {
3069
3157
  if (pct >= 80) {
3070
3158
  process.stderr.write(
3071
- chalk3.yellow(` \u26A0 Approaching free-tier limit. Upgrade: ${chalk3.bold("pretense upgrade")}
3159
+ chalk3.yellow(` \u26A0 Approaching free-tier limit. Upgrade: ${chalk3.bold("pretest upgrade")}
3072
3160
 
3073
3161
  `)
3074
3162
  );
3075
3163
  } else {
3076
3164
  process.stderr.write(
3077
- chalk3.gray(` Run ${chalk3.bold("pretense status")} for details, ${chalk3.bold("pretense upgrade")} to remove limits.
3165
+ chalk3.gray(` Run ${chalk3.bold("pretest status")} for details, ${chalk3.bold("pretest upgrade")} to remove limits.
3078
3166
 
3079
3167
  `)
3080
3168
  );
@@ -3086,19 +3174,19 @@ function printTokenFooter(filesScanned, mutationsMade) {
3086
3174
 
3087
3175
  // src/banner.ts
3088
3176
  import chalk4 from "chalk";
3089
- var BANNER_RAW = `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 pretense
3177
+ var BANNER_RAW = `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 pretest
3090
3178
  \u2588\u2588 \u2588\u2588
3091
3179
  \u2588\u2588 \u2588\u2588 Stop your code from
3092
3180
  \u2588\u2588 \u2588\u2588 leaking to any LLM.
3093
3181
  \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
3094
- \u2588\u2588 pretense.ai
3182
+ \u2588\u2588 @blockyfy/stg-cli
3095
3183
  \u2588\u2588
3096
3184
  \u2588\u2588
3097
3185
  \u2588\u2588
3098
3186
  \u2588\u2588`;
3099
3187
  var ICE_BLUE = "#7DD3FC";
3100
3188
  function shouldPrint() {
3101
- if (process.env.PRETENSE_NO_BANNER === "1") return false;
3189
+ if (DASHBOARD_NO_BANNER_ENVS.some((n) => process.env[n] === "1")) return false;
3102
3190
  if (!process.stdout.isTTY) return false;
3103
3191
  if (process.env.CI) return false;
3104
3192
  return true;
@@ -3143,7 +3231,7 @@ async function runStatus() {
3143
3231
  const tierBadge2 = plan === "ENTERPRISE" ? chalk5.bgMagenta.white.bold(" ENTERPRISE ") : plan === "PRO" ? chalk5.bgBlue.white.bold(" PRO ") : chalk5.bgGray.white.bold(" FREE ");
3144
3232
  const lines2 = [];
3145
3233
  lines2.push("");
3146
- lines2.push(`${chalk5.cyan("Pretense")} ${chalk5.gray(`v${getCliSemver()}`)} ${tierBadge2} ${chalk5.green("(synced)")}`);
3234
+ lines2.push(`${chalk5.cyan("Pretest")} ${chalk5.gray(`v${getCliSemver()}`)} ${tierBadge2} ${chalk5.green("(synced)")}`);
3147
3235
  lines2.push("");
3148
3236
  lines2.push(` Plan: ${chalk5.bold(plan)}`);
3149
3237
  lines2.push(` Mutations: ${fmt2(remote.mutationsUsed)} / ${fmt2(remote.monthlyMutationLimit)} this month`);
@@ -3157,7 +3245,7 @@ async function runStatus() {
3157
3245
  }
3158
3246
  lines2.push("");
3159
3247
  if (plan === "FREE") {
3160
- lines2.push(` ${chalk5.gray("Upgrade:")} ${chalk5.bold("pretense upgrade")}`);
3248
+ lines2.push(` ${chalk5.gray("Upgrade:")} ${chalk5.bold("pretest upgrade")}`);
3161
3249
  lines2.push("");
3162
3250
  }
3163
3251
  process.stdout.write(lines2.join("\n") + "\n");
@@ -3170,7 +3258,7 @@ async function runStatus() {
3170
3258
  const tierBadge = tier === "enterprise" ? chalk5.bgMagenta.white.bold(" ENTERPRISE ") : tier === "pro" ? chalk5.bgBlue.white.bold(" PRO ") : chalk5.bgGray.white.bold(" FREE ");
3171
3259
  const lines = [];
3172
3260
  lines.push("");
3173
- lines.push(`${chalk5.cyan("Pretense")} ${chalk5.gray(`v${getCliSemver()}`)} ${tierBadge} ${chalk5.yellow("(offline)")}`);
3261
+ lines.push(`${chalk5.cyan("Pretest")} ${chalk5.gray(`v${getCliSemver()}`)} ${tierBadge} ${chalk5.yellow("(offline)")}`);
3174
3262
  lines.push("");
3175
3263
  lines.push(` Plan: ${chalk5.bold(PLAN_LABEL[tier])} ${chalk5.gray("(" + planLimits.pricePerMonth + ")")}`);
3176
3264
  lines.push(` Mutations: ${fmt2(usage.mutations)} / ${fmt2(planLimits.monthlyMutations)} this month`);
@@ -3179,8 +3267,8 @@ async function runStatus() {
3179
3267
  lines.push(` Audit log: ${Number.isFinite(tierLimits.auditRetentionDays) ? `${tierLimits.auditRetentionDays} days` : "unlimited"}`);
3180
3268
  lines.push("");
3181
3269
  if (tier === "free") {
3182
- lines.push(` ${chalk5.gray("Upgrade:")} ${chalk5.bold("pretense upgrade")}`);
3183
- lines.push(` ${chalk5.gray("Credits:")} ${chalk5.bold("pretense credits")}`);
3270
+ lines.push(` ${chalk5.gray("Upgrade:")} ${chalk5.bold("pretest upgrade")}`);
3271
+ lines.push(` ${chalk5.gray("Credits:")} ${chalk5.bold("pretest credits")}`);
3184
3272
  lines.push("");
3185
3273
  }
3186
3274
  process.stdout.write(lines.join("\n") + "\n");
@@ -3188,12 +3276,12 @@ async function runStatus() {
3188
3276
 
3189
3277
  // src/commands/upgrade.ts
3190
3278
  import chalk6 from "chalk";
3191
- var PRICING_URL = "https://pretense.ai/pricing";
3279
+ var PRICING_URL = PUBLISH_PACKAGE_URL;
3192
3280
  function runUpgrade() {
3193
3281
  const tier = detectTier();
3194
3282
  const lines = [];
3195
3283
  lines.push("");
3196
- lines.push(chalk6.cyan.bold(" Pretense Plans"));
3284
+ lines.push(chalk6.cyan.bold(" Pretest Plans"));
3197
3285
  lines.push("");
3198
3286
  lines.push(chalk6.gray(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
3199
3287
  lines.push(chalk6.gray(" \u2502 \u2502 Free \u2502 Pro \u2502 Enterprise \u2502"));
@@ -3212,7 +3300,7 @@ function runUpgrade() {
3212
3300
  lines.push(` ${chalk6.gray("Upgrade at:")} ${chalk6.cyan.underline(PRICING_URL)}`);
3213
3301
  lines.push("");
3214
3302
  lines.push(chalk6.gray(" After purchase, set:"));
3215
- lines.push(chalk6.gray(" export PRETENSE_LICENSE_KEY=pre_pro_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
3303
+ lines.push(chalk6.gray(" export PRETEST_LICENSE_KEY=pre_pro_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
3216
3304
  lines.push("");
3217
3305
  process.stdout.write(lines.join("\n") + "\n");
3218
3306
  }
@@ -3251,7 +3339,7 @@ async function runCredits() {
3251
3339
  const pct2 = cap2 > 0 && cap2 !== -1 ? Math.round(used2 / cap2 * 100) : 0;
3252
3340
  const lines2 = [];
3253
3341
  lines2.push("");
3254
- lines2.push(chalk7.cyan.bold(" Pretense Credits") + " " + chalk7.green("(synced)"));
3342
+ lines2.push(chalk7.cyan.bold(" Pretest Credits") + " " + chalk7.green("(synced)"));
3255
3343
  lines2.push("");
3256
3344
  lines2.push(` Plan: ${chalk7.bold(remote.plan)}`);
3257
3345
  lines2.push(` Resets: ${new Date(remote.periodResetsAt).toLocaleDateString()}`);
@@ -3261,10 +3349,10 @@ async function runCredits() {
3261
3349
  lines2.push(` Remaining: ${fmt3(remaining2)}`);
3262
3350
  lines2.push("");
3263
3351
  if (remote.plan === "FREE" && cap2 !== -1 && used2 >= cap2 * 0.8) {
3264
- lines2.push(chalk7.yellow(" Warning: Approaching free-tier limit. Run 'pretense upgrade' for unlimited."));
3352
+ lines2.push(chalk7.yellow(" Warning: Approaching free-tier limit. Run 'pretest upgrade' for unlimited."));
3265
3353
  lines2.push("");
3266
3354
  } else if (remote.plan === "FREE") {
3267
- lines2.push(chalk7.gray(" Tip: Run 'pretense upgrade' to compare plans."));
3355
+ lines2.push(chalk7.gray(" Tip: Run 'pretest upgrade' to compare plans."));
3268
3356
  lines2.push("");
3269
3357
  }
3270
3358
  process.stdout.write(lines2.join("\n") + "\n");
@@ -3279,7 +3367,7 @@ async function runCredits() {
3279
3367
  const pct = Number.isFinite(cap) && cap > 0 ? Math.round(used / cap * 100) : 0;
3280
3368
  const lines = [];
3281
3369
  lines.push("");
3282
- lines.push(chalk7.cyan.bold(" Pretense Credits") + " " + chalk7.yellow("(offline)"));
3370
+ lines.push(chalk7.cyan.bold(" Pretest Credits") + " " + chalk7.yellow("(offline)"));
3283
3371
  lines.push("");
3284
3372
  lines.push(` Plan: ${chalk7.bold(PLAN_LABEL2[tier])}`);
3285
3373
  lines.push(` Month: ${usage.month}`);
@@ -3289,10 +3377,10 @@ async function runCredits() {
3289
3377
  lines.push(` Remaining: ${fmt3(remaining)}`);
3290
3378
  lines.push("");
3291
3379
  if (tier === "free" && Number.isFinite(cap) && used >= cap * 0.8) {
3292
- lines.push(chalk7.yellow(" Warning: Approaching free-tier limit. Run 'pretense upgrade' for unlimited."));
3380
+ lines.push(chalk7.yellow(" Warning: Approaching free-tier limit. Run 'pretest upgrade' for unlimited."));
3293
3381
  lines.push("");
3294
3382
  } else if (tier === "free") {
3295
- lines.push(chalk7.gray(" Tip: Run 'pretense upgrade' to compare plans."));
3383
+ lines.push(chalk7.gray(" Tip: Run 'pretest upgrade' to compare plans."));
3296
3384
  lines.push("");
3297
3385
  }
3298
3386
  process.stdout.write(lines.join("\n") + "\n");
@@ -3303,14 +3391,16 @@ import readline2 from "readline/promises";
3303
3391
  import chalk8 from "chalk";
3304
3392
  async function runLogout(opts = {}) {
3305
3393
  if (!loadApiKey()) {
3306
- console.log(chalk8.gray("No saved Pretense dashboard API key in ~/.pretense/config.json."));
3307
- console.log(chalk8.gray("If you use PRETENSE_API_KEY in your shell, run unset PRETENSE_API_KEY."));
3394
+ console.log(chalk8.gray("No saved dashboard API key in ~/.pretest/config.json."));
3395
+ console.log(
3396
+ chalk8.gray("If you use PRETEST_API_KEY in your shell, run unset PRETEST_API_KEY.")
3397
+ );
3308
3398
  return 0;
3309
3399
  }
3310
3400
  if (!opts.assumeYes) {
3311
3401
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
3312
3402
  console.error(chalk8.red("Error: confirmation requires an interactive terminal."));
3313
- console.error(chalk8.gray("Run `pretense logout --yes` to skip the prompt."));
3403
+ console.error(chalk8.gray("Run `pretest logout --yes` to skip the prompt."));
3314
3404
  return 1;
3315
3405
  }
3316
3406
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
@@ -3327,17 +3417,19 @@ async function runLogout(opts = {}) {
3327
3417
  rl.close();
3328
3418
  }
3329
3419
  }
3330
- const hadEnvDashboardKey = !!process.env["PRETENSE_API_KEY"]?.trim();
3420
+ const hadEnvDashboardKey = hasDashboardApiKeyInEnv();
3331
3421
  const { removed, path } = removeSavedDashboardCredentials();
3332
3422
  clearValidationCache();
3333
- delete process.env["PRETENSE_API_KEY"];
3423
+ clearDashboardApiKeyFromProcess();
3334
3424
  if (removed) {
3335
3425
  console.log(chalk8.green("Logged out. Removed saved API key from"), chalk8.bold(path));
3336
- console.log(chalk8.gray("Other terminals: run unset PRETENSE_API_KEY if that variable is still exported (e.g. in ~/.zshrc)."));
3426
+ console.log(
3427
+ chalk8.gray("Other terminals: run unset PRETEST_API_KEY if that variable is still exported (e.g. in ~/.zshrc).")
3428
+ );
3337
3429
  if (hadEnvDashboardKey) {
3338
3430
  console.log(
3339
3431
  chalk8.yellow(
3340
- "This shell had PRETENSE_API_KEY set; it was cleared for this process only. Restart any running pretense proxy (Ctrl+C, then pretense start)."
3432
+ "This shell had a dashboard key in the environment; it was cleared for this process only. Restart any running pretest proxy (Ctrl+C, then pretest start)."
3341
3433
  )
3342
3434
  );
3343
3435
  }
@@ -3350,7 +3442,7 @@ async function runLogout(opts = {}) {
3350
3442
  const major = parseInt(process.versions.node.split(".")[0], 10);
3351
3443
  if (Number.isNaN(major) || major < 18) {
3352
3444
  process.stderr.write(
3353
- `pretense requires Node.js 18 or newer (you have v${process.versions.node}).
3445
+ `pretest requires Node.js 18 or newer (you have v${process.versions.node}).
3354
3446
  `
3355
3447
  );
3356
3448
  process.stderr.write(`Upgrade via nvm: nvm install 20 && nvm use 20
@@ -3482,7 +3574,7 @@ function validateLanguage(lang) {
3482
3574
  }
3483
3575
  function collectFiles(target) {
3484
3576
  const abs = resolve2(target);
3485
- if (!existsSync7(abs)) {
3577
+ if (!existsSync8(abs)) {
3486
3578
  return [];
3487
3579
  }
3488
3580
  const stat = statSync(abs);
@@ -3500,13 +3592,14 @@ function collectFiles(target) {
3500
3592
  ".git",
3501
3593
  "dist",
3502
3594
  "build",
3595
+ ".pretest",
3503
3596
  ".pretense",
3504
3597
  ".next",
3505
3598
  "__pycache__",
3506
3599
  ".Trash"
3507
3600
  ]);
3508
3601
  for (const entry of entries) {
3509
- const fullPath = join5(dir, entry.name);
3602
+ const fullPath = join6(dir, entry.name);
3510
3603
  if (entry.isDirectory()) {
3511
3604
  if (skipDirs.has(entry.name)) continue;
3512
3605
  walk(fullPath);
@@ -3519,12 +3612,12 @@ function collectFiles(target) {
3519
3612
  return files;
3520
3613
  }
3521
3614
  var program = new Command();
3522
- program.name("pretense").description("AI firewall CLI \u2014 mutates proprietary code before LLM API calls").version(VERSION).hook("preAction", () => {
3615
+ program.name("pretest").description("AI firewall CLI \u2014 mutates proprietary code before LLM API calls").version(VERSION).hook("preAction", () => {
3523
3616
  printBanner();
3524
3617
  });
3525
- program.command("init").description("Initialize .pretense/ config in current directory").option("-d, --dir <path>", "Target directory", process.cwd()).action((opts) => {
3618
+ program.command("init").description("Initialize .pretest/ config in current directory").option("-d, --dir <path>", "Target directory", process.cwd()).action((opts) => {
3526
3619
  const dir = resolve2(opts.dir);
3527
- console.log(chalk9.cyan("Initializing Pretense in"), chalk9.bold(dir));
3620
+ console.log(chalk9.cyan("Initializing Pretest in"), chalk9.bold(dir));
3528
3621
  const configDir = initConfig(dir);
3529
3622
  const files = collectFiles(dir);
3530
3623
  const langCounts = {};
@@ -3532,16 +3625,16 @@ program.command("init").description("Initialize .pretense/ config in current dir
3532
3625
  const lang = langFromExt(f);
3533
3626
  langCounts[lang] = (langCounts[lang] ?? 0) + 1;
3534
3627
  }
3535
- console.log(chalk9.green("\n .pretense/ created at"), chalk9.bold(configDir));
3628
+ console.log(chalk9.green("\n .pretest/ created at"), chalk9.bold(configDir));
3536
3629
  console.log(chalk9.gray(`
3537
3630
  Scanned ${files.length} source files:`));
3538
3631
  for (const [lang, count] of Object.entries(langCounts)) {
3539
3632
  console.log(chalk9.gray(` ${lang}: ${count} files`));
3540
3633
  }
3541
- console.log(chalk9.cyan("\n Next: run"), chalk9.bold("pretense start"), chalk9.cyan("to launch the proxy"));
3634
+ console.log(chalk9.cyan("\n Next: run"), chalk9.bold("pretest start"), chalk9.cyan("to launch the proxy"));
3542
3635
  console.log();
3543
3636
  });
3544
- program.command("start").description("Start the Pretense proxy server").option("-p, --port <number>", "Port number", "9339").option("-v, --verbose", "Enable verbose logging", false).action(async (opts) => {
3637
+ program.command("start").description("Start the Pretest proxy server").option("-p, --port <number>", "Port number", "9339").option("-v, --verbose", "Enable verbose logging", false).action(async (opts) => {
3545
3638
  const config = loadConfig();
3546
3639
  const port = validatePort(opts.port);
3547
3640
  if (port === null) {
@@ -3660,7 +3753,7 @@ function parseSizeOption(value) {
3660
3753
  }
3661
3754
  program.command("scan <target>").description("Scan file or directory for identifiers and secrets (no mutation)").option("--secrets-only", "Only scan for secrets/credentials", false).option("--json", "Output as JSON", false).option("--max-file-size <size>", "Skip files larger than this (e.g. 10mb, 500k)", "10mb").option("--concurrency <n>", "Max files scanned in parallel", String(SCAN_CONCURRENCY)).option("--quiet", "Suppress progress output", false).action(async (target, opts) => {
3662
3755
  const absTarget = resolve2(target);
3663
- if (!existsSync7(absTarget)) {
3756
+ if (!existsSync8(absTarget)) {
3664
3757
  console.error(chalk9.red("Error: Path not found:"), chalk9.bold(absTarget));
3665
3758
  process.exit(1);
3666
3759
  }
@@ -3708,7 +3801,7 @@ program.command("scan <target>").description("Scan file or directory for identif
3708
3801
  interrupted
3709
3802
  }, null, 2));
3710
3803
  } else {
3711
- console.log(chalk9.cyan("\nPretense Scan Results\n"));
3804
+ console.log(chalk9.cyan("\nPretest Scan Results\n"));
3712
3805
  for (const r of allResults) {
3713
3806
  if (r.skipped) {
3714
3807
  if (r.skipped === "too-large") {
@@ -3749,9 +3842,9 @@ program.command("scan <target>").description("Scan file or directory for identif
3749
3842
  process.exit(2);
3750
3843
  }
3751
3844
  });
3752
- program.command("mutate <file>").description("Mutate identifiers for stdout (scanner redacts secrets/PII in the source first)").option("-s, --seed <seed>", "Mutation seed", "pretense").option("-l, --language <lang>", "Source language (typescript, javascript, python, go, java, csharp, ruby, rust)").option("--save", "Save mutation map to .pretense/", false).option("--json", "Output as JSON (includes map + stats)", false).action((file, opts) => {
3845
+ program.command("mutate <file>").description("Mutate identifiers for stdout (scanner redacts secrets/PII in the source first)").option("-s, --seed <seed>", "Mutation seed", "pretest").option("-l, --language <lang>", "Source language (typescript, javascript, python, go, java, csharp, ruby, rust)").option("--save", "Save mutation map to .pretest/", false).option("--json", "Output as JSON (includes map + stats)", false).action((file, opts) => {
3753
3846
  const absPath = resolve2(file);
3754
- if (!existsSync7(absPath)) {
3847
+ if (!existsSync8(absPath)) {
3755
3848
  console.error(chalk9.red("Error: File not found:"), chalk9.bold(absPath));
3756
3849
  process.exit(1);
3757
3850
  }
@@ -3771,13 +3864,13 @@ program.command("mutate <file>").description("Mutate identifiers for stdout (sca
3771
3864
  const code = readFileSync7(absPath, "utf-8");
3772
3865
  const lang = opts.language ? validateLanguage(opts.language) : langFromExt(absPath);
3773
3866
  const secretScan = scan2(code);
3774
- const effectiveSeed = opts.seed === "pretense" ? buildSaltedSeed(opts.seed) : opts.seed;
3867
+ const effectiveSeed = effectiveSeedForMutation(opts.seed);
3775
3868
  const { redactedCode: redacted, secretsMap } = applyRedactionsTracked(code, secretScan.matches, effectiveSeed);
3776
3869
  const secretsRedacted = secretsMap.size;
3777
3870
  const result = mutate(redacted, lang, opts.seed);
3778
3871
  if (opts.save) {
3779
3872
  const configDir = getConfigDir();
3780
- const store = new MutationStore(join5(configDir, "mutation-map.json"));
3873
+ const store = new MutationStore(join6(configDir, "mutation-map.json"));
3781
3874
  store.load();
3782
3875
  store.save({
3783
3876
  id: absPath,
@@ -3815,15 +3908,15 @@ program.command("mutate <file>").description("Mutate identifiers for stdout (sca
3815
3908
  });
3816
3909
  program.command("reverse <file>").description("Reverse mutations using stored map").option("-m, --map <path>", "Path to mutation map JSON file").action((file, opts) => {
3817
3910
  const absPath = resolve2(file);
3818
- if (!existsSync7(absPath)) {
3911
+ if (!existsSync8(absPath)) {
3819
3912
  console.error(chalk9.red("Error: File not found:"), chalk9.bold(absPath));
3820
3913
  process.exit(1);
3821
3914
  }
3822
3915
  const mutatedCode = readFileSync7(absPath, "utf-8");
3823
- const mapPath = opts.map ? resolve2(opts.map) : join5(getConfigDir(), "mutation-map.json");
3824
- if (!existsSync7(mapPath)) {
3916
+ const mapPath = opts.map ? resolve2(opts.map) : join6(getConfigDir(), "mutation-map.json");
3917
+ if (!existsSync8(mapPath)) {
3825
3918
  console.error(chalk9.red("Error: Mutation map not found:"), chalk9.bold(mapPath));
3826
- console.error(chalk9.gray("Run 'pretense mutate --save' first, or specify --map <path>"));
3919
+ console.error(chalk9.gray("Run 'pretest mutate --save' first, or specify --map <path>"));
3827
3920
  process.exit(1);
3828
3921
  }
3829
3922
  let store;
@@ -3832,13 +3925,13 @@ program.command("reverse <file>").description("Reverse mutations using stored ma
3832
3925
  store.load();
3833
3926
  } catch {
3834
3927
  console.error(chalk9.red("Error: Failed to load mutation map:"), chalk9.bold(mapPath));
3835
- console.error(chalk9.gray("The file may be corrupted. Run 'pretense mutate --save' to regenerate."));
3928
+ console.error(chalk9.gray("The file may be corrupted. Run 'pretest mutate --save' to regenerate."));
3836
3929
  process.exit(1);
3837
3930
  }
3838
3931
  const entry = store.get(absPath) ?? store.getByHash(absPath) ?? store.list(1)[0];
3839
3932
  if (!entry) {
3840
3933
  console.error(chalk9.red("Error: No mutation map entries found."));
3841
- console.error(chalk9.gray("Run 'pretense mutate --save <file>' first to generate a map."));
3934
+ console.error(chalk9.gray("Run 'pretest mutate --save <file>' first to generate a map."));
3842
3935
  process.exit(1);
3843
3936
  }
3844
3937
  const map = MutationStore.toMap(entry);
@@ -3858,16 +3951,16 @@ program.command("audit").description("View the audit log").option("--json", "Out
3858
3951
  const output = formatAudit(entries, format);
3859
3952
  console.log(output);
3860
3953
  });
3861
- program.command("version").description("Print Pretense CLI version").action(() => {
3862
- console.log(`@pretense/cli v${VERSION}`);
3954
+ program.command("version").description("Print Pretest CLI version").action(() => {
3955
+ console.log(`@blockyfy/stg-cli v${VERSION}`);
3863
3956
  });
3864
3957
  program.command("status").description("Show current plan, monthly quota, seat usage").action(async () => {
3865
3958
  await runStatus();
3866
3959
  });
3867
- program.command("usage").description("Alias for `pretense status` \u2014 show monthly quota usage").action(async () => {
3960
+ program.command("usage").description("Alias for `pretest status` \u2014 show monthly quota usage").action(async () => {
3868
3961
  await runStatus();
3869
3962
  });
3870
- program.command("tokens").description("Alias for `pretense credits` \u2014 show remaining mutation budget").action(async () => {
3963
+ program.command("tokens").description("Alias for `pretest credits` \u2014 show remaining mutation budget").action(async () => {
3871
3964
  await runCredits();
3872
3965
  });
3873
3966
  program.command("upgrade").description("Compare plans and upgrade to Pro or Enterprise").action(() => {
@@ -3876,11 +3969,11 @@ program.command("upgrade").description("Compare plans and upgrade to Pro or Ente
3876
3969
  program.command("credits").description("Show remaining mutation/scan budget for the current month").action(async () => {
3877
3970
  await runCredits();
3878
3971
  });
3879
- program.command("login").description("Save a Pretense API key to ~/.pretense/config.json for future CLI runs").option("-k, --key <key>", "API key (prtns_live_... or pk_live_...). If omitted, read from $PRETENSE_API_KEY or stdin.").action((opts) => {
3972
+ program.command("login").description("Save a dashboard API key to ~/.pretest/config.json for future CLI runs").option("-k, --key <key>", "API key (prtns_live_... or pk_live_...). If omitted, read from $PRETEST_API_KEY or stdin.").action((opts) => {
3880
3973
  const code = runLogin({ key: opts.key });
3881
3974
  if (code !== 0) process.exit(code);
3882
3975
  });
3883
- program.command("logout").description("Remove the saved Pretense dashboard API key from ~/.pretense/config.json").option("-y, --yes", "Skip confirmation prompt", false).action(async (opts) => {
3976
+ program.command("logout").description("Remove the saved dashboard API key from ~/.pretest/config.json").option("-y, --yes", "Skip confirmation prompt", false).action(async (opts) => {
3884
3977
  const code = await runLogout({ assumeYes: opts.yes === true });
3885
3978
  if (code !== 0) process.exit(code);
3886
3979
  });