@rosh100yx/outlier 0.4.25 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/outlier.js CHANGED
@@ -31,6 +31,20 @@ var __toESM = (mod, isNodeMode, target) => {
31
31
  return to;
32
32
  };
33
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __returnValue = (v) => v;
35
+ function __exportSetter(name, newValue) {
36
+ this[name] = __returnValue.bind(null, newValue);
37
+ }
38
+ var __export = (target, all) => {
39
+ for (var name in all)
40
+ __defProp(target, name, {
41
+ get: all[name],
42
+ enumerable: true,
43
+ configurable: true,
44
+ set: __exportSetter.bind(all, name)
45
+ });
46
+ };
47
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
34
48
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
35
49
 
36
50
  // node_modules/sisteransi/src/index.js
@@ -161,11 +175,52 @@ var require_picocolors = __commonJS((exports, module) => {
161
175
  module.exports.createColors = createColors;
162
176
  });
163
177
 
178
+ // src/economics.ts
179
+ var exports_economics = {};
180
+ __export(exports_economics, {
181
+ projectEconomics: () => projectEconomics
182
+ });
183
+ function projectEconomics(input) {
184
+ const team = input.teamSize ?? DEFAULTS.teamSize;
185
+ const days = input.workdaysPerYear ?? DEFAULTS.workdaysPerYear;
186
+ const ai = Math.max(0, Math.min(1, input.aiRatio));
187
+ const annualOutflowPerDev = input.estUsdSession * (days / 30);
188
+ const annualOutflowTeam = annualOutflowPerDev * team;
189
+ const projections = [
190
+ {
191
+ label: "Authorship shift",
192
+ value: `${(ai * 100).toFixed(0)}% of output → AI`,
193
+ note: team > 1 ? `≈ ${(ai * team).toFixed(1)} of ${team} dev-equivalents of authorship now machine-produced.` : "At team scale, this many dev-equivalents move to the machine."
194
+ },
195
+ {
196
+ label: "Value capture (offshore)",
197
+ value: `~$${Math.round(annualOutflowTeam).toLocaleString()}/yr`,
198
+ note: "Hard-currency spend leaving to a foreign AI vendor — value captured offshore, not by the local worker."
199
+ },
200
+ {
201
+ label: "Skill ladder",
202
+ value: ai > 0.7 ? "AT RISK" : ai > 0.4 ? "watch" : "intact",
203
+ note: ai > 0.7 ? "Above ~70%, juniors stop building the skill that makes seniors — premature deprofessionalization." : "Humans still author enough core work to keep building expertise."
204
+ },
205
+ {
206
+ label: "Forex / tax base",
207
+ value: `$${Math.round(annualOutflowPerDev).toLocaleString()}/dev/yr imported`,
208
+ note: "Locally-taxed wages give way to foreign-billed inference: income-tax erosion + a recurring forex import."
209
+ }
210
+ ];
211
+ const assumptions = `Projection only. Assumes: team of ${team}, the local log window ≈ one month of work, ` + `${days} workdays/yr. Spend is your measured/estimated local outflow scaled up — an order-of-magnitude shadow, not an audit.`;
212
+ return { projections, assumptions };
213
+ }
214
+ var DEFAULTS;
215
+ var init_economics = __esm(() => {
216
+ DEFAULTS = { teamSize: 1, workdaysPerYear: 230 };
217
+ });
218
+
164
219
  // package.json
165
220
  var require_package = __commonJS((exports, module) => {
166
221
  module.exports = {
167
222
  name: "@rosh100yx/outlier",
168
- version: "0.4.25",
223
+ version: "0.10.2",
169
224
  description: "AI Code Governance & Capability Auditing for the Terminal. Measures AI reliance, context waste, and enforces local CI/CD policies.",
170
225
  bin: {
171
226
  outlier: "bin/outlier.js"
@@ -1798,38 +1853,192 @@ async function getAuthorshipStats(repoPath = process.cwd()) {
1798
1853
  }
1799
1854
 
1800
1855
  // src/carbon.ts
1801
- import { homedir } from "os";
1802
- import { join } from "path";
1856
+ import { homedir as homedir2 } from "os";
1857
+ import { join as join2 } from "path";
1803
1858
  import { readFile, access, readdir } from "fs/promises";
1804
1859
  // data/grid-factors.json
1805
1860
  var grid_factors_default = {
1806
1861
  vietnam: 681,
1807
- france: 21.7,
1808
- us_east: 380,
1862
+ india_average: 715,
1863
+ indonesia: 650,
1864
+ china: 581,
1809
1865
  singapore: 408,
1810
- india_average: 715
1866
+ japan: 470,
1867
+ south_korea: 415,
1868
+ australia: 510,
1869
+ us_east: 380,
1870
+ us_west: 210,
1871
+ canada: 120,
1872
+ brazil: 95,
1873
+ uk: 210,
1874
+ germany: 350,
1875
+ france: 21.7,
1876
+ norway: 28,
1877
+ sweden: 41,
1878
+ global_average: 450
1811
1879
  };
1812
1880
 
1881
+ // src/emissions.ts
1882
+ var MODEL_ENERGY_KWH_PER_M_OUTPUT = {
1883
+ opus: 0.66,
1884
+ sonnet: 0.3,
1885
+ haiku: 0.1,
1886
+ "gpt-4": 0.55,
1887
+ "gpt-4o": 0.3,
1888
+ "gpt-5": 0.45,
1889
+ gemini: 0.35,
1890
+ flash: 0.1,
1891
+ local: 0.5,
1892
+ default: 0.45
1893
+ };
1894
+ function modelClass(modelId) {
1895
+ const m2 = (modelId || "").toLowerCase();
1896
+ if (m2.includes("opus"))
1897
+ return "opus";
1898
+ if (m2.includes("sonnet"))
1899
+ return "sonnet";
1900
+ if (m2.includes("haiku"))
1901
+ return "haiku";
1902
+ if (m2.includes("flash") || m2.includes("mini"))
1903
+ return "haiku";
1904
+ if (m2.includes("gpt-5"))
1905
+ return "gpt-5";
1906
+ if (m2.includes("gpt-4o"))
1907
+ return "gpt-4o";
1908
+ if (m2.includes("gpt-4"))
1909
+ return "gpt-4";
1910
+ if (m2.includes("gemini"))
1911
+ return "gemini";
1912
+ if (m2.includes("llama") || m2.includes("qwen") || m2.includes("mistral") || m2.includes("local"))
1913
+ return "local";
1914
+ return "default";
1915
+ }
1916
+ function energyKwhForModel(modelId, outputTokens) {
1917
+ const cls = modelClass(modelId);
1918
+ const coeff = MODEL_ENERGY_KWH_PER_M_OUTPUT[cls] ?? 0.45;
1919
+ return outputTokens / 1e6 * coeff;
1920
+ }
1921
+ function energyKwhByModel(outputByModel) {
1922
+ let kwh = 0;
1923
+ for (const [model, out] of Object.entries(outputByModel)) {
1924
+ kwh += energyKwhForModel(model, out);
1925
+ }
1926
+ return kwh;
1927
+ }
1928
+
1929
+ // src/sources.ts
1930
+ import { homedir } from "os";
1931
+ import { join } from "path";
1932
+ import { existsSync } from "fs";
1933
+ import { execSync } from "child_process";
1934
+ var HOME = homedir();
1935
+ function hasCli(cmd) {
1936
+ try {
1937
+ execSync(`command -v ${cmd}`, { stdio: "ignore" });
1938
+ return true;
1939
+ } catch {
1940
+ return false;
1941
+ }
1942
+ }
1943
+ function hasPath(p2) {
1944
+ try {
1945
+ return existsSync(p2);
1946
+ } catch {
1947
+ return false;
1948
+ }
1949
+ }
1950
+ function detectSources(cwd = process.cwd()) {
1951
+ const tools = [];
1952
+ const add = (t2) => {
1953
+ if (!tools.includes(t2))
1954
+ tools.push(t2);
1955
+ };
1956
+ const cliTools = {
1957
+ claude: "claude",
1958
+ cursor: "cursor",
1959
+ aider: "aider",
1960
+ gemini: "gemini",
1961
+ opencode: "opencode",
1962
+ cody: "cody",
1963
+ continue: "continue",
1964
+ codex: "codex"
1965
+ };
1966
+ for (const [name, cmd] of Object.entries(cliTools)) {
1967
+ if (hasCli(cmd))
1968
+ add(name);
1969
+ }
1970
+ for (const [name, dir] of Object.entries({
1971
+ claude: ".claude",
1972
+ cursor: ".cursor",
1973
+ gemini: ".gemini",
1974
+ codeium: ".codeium",
1975
+ continue: ".continue",
1976
+ aider: ".aider.conf.yml"
1977
+ })) {
1978
+ if (hasPath(join(HOME, dir)))
1979
+ add(name);
1980
+ }
1981
+ if (hasCli("codecarbon"))
1982
+ add("codecarbon");
1983
+ if (hasCli("ccusage"))
1984
+ add("ccusage");
1985
+ const slug = cwd.replace(/\//g, "-");
1986
+ const claudeProjectDir = join(HOME, ".claude", "projects", slug);
1987
+ const tokenomicsLog = join(HOME, ".claude", "tokenomics-log.jsonl");
1988
+ let tokenSource;
1989
+ if (hasPath(tokenomicsLog)) {
1990
+ tokenSource = { name: "caveman tokenomics log", provenance: "measured" };
1991
+ } else if (hasPath(claudeProjectDir)) {
1992
+ tokenSource = { name: "Claude Code transcripts", provenance: "estimated" };
1993
+ } else if (tools.includes("ccusage")) {
1994
+ tokenSource = { name: "ccusage", provenance: "estimated" };
1995
+ } else {
1996
+ tokenSource = { name: "none", provenance: "none" };
1997
+ }
1998
+ let carbonSource;
1999
+ const codecarbonData = hasPath(join(cwd, "emissions.csv")) || hasPath(join(HOME, ".codecarbon", "emissions.csv"));
2000
+ if (codecarbonData) {
2001
+ carbonSource = { name: "CodeCarbon emissions.csv", provenance: "measured" };
2002
+ } else if (tokenSource.provenance !== "none") {
2003
+ carbonSource = { name: "model+grid estimate", provenance: "estimated" };
2004
+ } else {
2005
+ carbonSource = { name: "none", provenance: "none" };
2006
+ }
2007
+ let capabilitySource;
2008
+ if (hasPath(join(HOME, ".claude", "settings.json")) || hasPath(join(cwd, "AGENTS.md")) || hasPath(join(cwd, ".mcp.json"))) {
2009
+ capabilitySource = { name: "local config (settings/AGENTS/MCP)", provenance: "measured" };
2010
+ } else {
2011
+ capabilitySource = { name: "none", provenance: "none" };
2012
+ }
2013
+ return { tools, tokenSource, carbonSource, capabilitySource };
2014
+ }
2015
+ function provLabel(s) {
2016
+ if (s.provenance === "none")
2017
+ return "no local data";
2018
+ return `${s.provenance} · ${s.name}`;
2019
+ }
2020
+
1813
2021
  // src/carbon.ts
1814
2022
  class ClaudeLogParser {
1815
2023
  baseDir;
1816
2024
  cwd;
1817
- constructor(baseDir = homedir(), cwd = process.cwd()) {
2025
+ constructor(baseDir = homedir2(), cwd = process.cwd()) {
1818
2026
  this.baseDir = baseDir;
1819
2027
  this.cwd = cwd;
1820
2028
  }
1821
2029
  async parse() {
1822
2030
  const slug = this.cwd.replace(/\//g, "-");
1823
- const projectDir = join(this.baseDir, ".claude", "projects", slug);
2031
+ const projectDir = join2(this.baseDir, ".claude", "projects", slug);
1824
2032
  try {
1825
2033
  const files = (await readdir(projectDir)).filter((f2) => f2.endsWith(".jsonl"));
1826
2034
  if (files.length > 0) {
1827
2035
  let total2 = 0, output2 = 0, cache2 = 0;
1828
2036
  const sessions2 = new Set;
2037
+ const outputByModel2 = {};
1829
2038
  for (const file of files) {
1830
2039
  let text3 = "";
1831
2040
  try {
1832
- text3 = await readFile(join(projectDir, file), "utf-8");
2041
+ text3 = await readFile(join2(projectDir, file), "utf-8");
1833
2042
  } catch {
1834
2043
  continue;
1835
2044
  }
@@ -1839,7 +2048,8 @@ class ClaudeLogParser {
1839
2048
  continue;
1840
2049
  try {
1841
2050
  const d = JSON.parse(line);
1842
- const u4 = d.message && d.message.usage || d.usage;
2051
+ const msg = d.message || {};
2052
+ const u4 = msg.usage || d.usage;
1843
2053
  if (u4) {
1844
2054
  const inp = u4.input_tokens || 0;
1845
2055
  const out = u4.output_tokens || 0;
@@ -1848,24 +2058,27 @@ class ClaudeLogParser {
1848
2058
  total2 += inp + out + cr + cw;
1849
2059
  output2 += out;
1850
2060
  cache2 += cr;
2061
+ const model = msg.model || "default";
2062
+ outputByModel2[model] = (outputByModel2[model] || 0) + out;
1851
2063
  }
1852
2064
  if (d.sessionId)
1853
2065
  sessions2.add(d.sessionId);
1854
2066
  } catch {}
1855
2067
  }
1856
2068
  }
1857
- return { total: total2, output: output2, cache: cache2, sessions: sessions2.size, cost: 0 };
2069
+ return { total: total2, output: output2, cache: cache2, sessions: sessions2.size, cost: 0, outputByModel: outputByModel2 };
1858
2070
  }
1859
2071
  } catch {}
1860
- const logPath = join(this.baseDir, ".claude", "tokenomics-log.jsonl");
2072
+ const logPath = join2(this.baseDir, ".claude", "tokenomics-log.jsonl");
1861
2073
  try {
1862
2074
  await access(logPath);
1863
2075
  } catch {
1864
- return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0 };
2076
+ return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0, outputByModel: {} };
1865
2077
  }
1866
2078
  const text2 = await readFile(logPath, "utf-8");
1867
2079
  let total = 0, output = 0, cache = 0, cost = 0;
1868
2080
  const sessions = new Set;
2081
+ const outputByModel = {};
1869
2082
  for (const line of text2.split(`
1870
2083
  `)) {
1871
2084
  if (!line.trim())
@@ -1878,21 +2091,50 @@ class ClaudeLogParser {
1878
2091
  cost += data.cost_usd || 0;
1879
2092
  if (data.session_id)
1880
2093
  sessions.add(data.session_id);
2094
+ const model = data.model || "default";
2095
+ outputByModel[model] = (outputByModel[model] || 0) + (data.output_tokens || 0);
1881
2096
  } catch {}
1882
2097
  }
1883
- return { total, output, cache, sessions: sessions.size, cost };
2098
+ return { total, output, cache, sessions: sessions.size, cost, outputByModel };
1884
2099
  }
1885
2100
  }
1886
2101
 
1887
2102
  class CursorLogParser {
1888
2103
  async parse() {
1889
- return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0 };
2104
+ return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0, outputByModel: {} };
1890
2105
  }
1891
2106
  }
1892
2107
  function estimateUsd(output, cacheRead, total) {
1893
2108
  const otherInput = Math.max(0, total - output - cacheRead);
1894
2109
  return output / 1e6 * 9 + cacheRead / 1e6 * 0.3 + otherInput / 1e6 * 3;
1895
2110
  }
2111
+ function readCodeCarbon(cwd, home) {
2112
+ const { readFileSync, existsSync: existsSync2 } = __require("fs");
2113
+ const { join: join3 } = __require("path");
2114
+ for (const p2 of [join3(cwd, "emissions.csv"), join3(home, ".codecarbon", "emissions.csv")]) {
2115
+ try {
2116
+ if (!existsSync2(p2))
2117
+ continue;
2118
+ const lines = readFileSync(p2, "utf-8").trim().split(`
2119
+ `);
2120
+ if (lines.length < 2)
2121
+ continue;
2122
+ const header = lines[0].split(",");
2123
+ const iEm = header.indexOf("emissions");
2124
+ const iEn = header.indexOf("energy_consumed");
2125
+ if (iEm === -1 && iEn === -1)
2126
+ continue;
2127
+ let co2 = 0, kwh = 0;
2128
+ for (const row of lines.slice(1)) {
2129
+ const cols = row.split(",");
2130
+ co2 += parseFloat(cols[iEm]) || 0;
2131
+ kwh += parseFloat(cols[iEn]) || 0;
2132
+ }
2133
+ return { energyKwh: kwh, co2Kg: co2 };
2134
+ } catch {}
2135
+ }
2136
+ return null;
2137
+ }
1896
2138
  function getLocalGridFactor() {
1897
2139
  try {
1898
2140
  const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -1907,11 +2149,12 @@ function getLocalGridFactor() {
1907
2149
  if (tz.includes("Calcutta") || tz.includes("Kolkata") || tz.includes("Asia/Kabul"))
1908
2150
  return { region: "India", factor: grid_factors_default.india_average };
1909
2151
  } catch (e) {}
1910
- return { region: "Global Average", factor: 450 };
2152
+ return { region: "Global Average", factor: grid_factors_default.global_average };
1911
2153
  }
1912
2154
  async function getCarbonStats() {
1913
2155
  const parsers = [new ClaudeLogParser, new CursorLogParser];
1914
2156
  let totalTokens = 0, outputTokens = 0, cacheReadTokens = 0, sessions = 0, loggedCost = 0;
2157
+ const outputByModel = {};
1915
2158
  for (const parser of parsers) {
1916
2159
  const stats = await parser.parse();
1917
2160
  totalTokens += stats.total;
@@ -1919,9 +2162,15 @@ async function getCarbonStats() {
1919
2162
  cacheReadTokens += stats.cache;
1920
2163
  sessions += stats.sessions;
1921
2164
  loggedCost += stats.cost;
2165
+ for (const [m2, out] of Object.entries(stats.outputByModel)) {
2166
+ outputByModel[m2] = (outputByModel[m2] || 0) + out;
2167
+ }
1922
2168
  }
1923
- const energyKwh = outputTokens / 1e6 * 0.662;
1924
2169
  const localGrid = getLocalGridFactor();
2170
+ const measured = readCodeCarbon(process.cwd(), homedir2());
2171
+ const energyKwh = measured ? measured.energyKwh : energyKwhByModel(outputByModel);
2172
+ const measuredCo2 = measured ? measured.co2Kg : null;
2173
+ const sources = detectSources();
1925
2174
  const costIsReal = loggedCost > 0;
1926
2175
  const estUsd = costIsReal ? loggedCost : estimateUsd(outputTokens, cacheReadTokens, totalTokens);
1927
2176
  return {
@@ -1931,84 +2180,271 @@ async function getCarbonStats() {
1931
2180
  energyKwh,
1932
2181
  co2KgVietnam: energyKwh * grid_factors_default.vietnam / 1000,
1933
2182
  co2KgFrance: energyKwh * grid_factors_default.france / 1000,
1934
- localCo2Kg: energyKwh * localGrid.factor / 1000,
1935
- localRegion: localGrid.region,
2183
+ localCo2Kg: measuredCo2 !== null ? measuredCo2 : energyKwh * localGrid.factor / 1000,
2184
+ localRegion: measured ? "CodeCarbon (measured)" : localGrid.region,
1936
2185
  sessions,
1937
2186
  estUsd,
1938
- costIsReal
2187
+ costIsReal,
2188
+ tokenProvenance: sources.tokenSource.provenance,
2189
+ carbonProvenance: sources.carbonSource.provenance,
2190
+ sourceLabel: provLabel(sources.tokenSource)
1939
2191
  };
1940
2192
  }
1941
2193
 
1942
2194
  // src/capabilities.ts
1943
- import { homedir as homedir2 } from "os";
1944
- import { join as join2 } from "path";
1945
- import { existsSync, readdirSync } from "fs";
1946
- async function getCapabilitiesStats(repoPath = process.cwd(), homeDirPath = homedir2()) {
1947
- const stats = {
1948
- mcps: [],
1949
- skills: [],
1950
- hasOrchestration: false
1951
- };
1952
- if (existsSync(join2(repoPath, "AGENTS.md"))) {
1953
- stats.hasOrchestration = true;
1954
- }
1955
- const projectSkillsPath = join2(repoPath, ".agents", "skills");
1956
- if (existsSync(projectSkillsPath)) {
1957
- try {
1958
- const skills = readdirSync(projectSkillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
1959
- stats.skills.push(...skills);
1960
- } catch (e) {}
2195
+ import { homedir as homedir3 } from "os";
2196
+ import { join as join3 } from "path";
2197
+ import { existsSync as existsSync2, readdirSync, readFileSync } from "fs";
2198
+ function classifyReach(name) {
2199
+ const n2 = name.toLowerCase();
2200
+ if (/(stripe|payment|infinity|kucoin|wallet|billing|payout)/.test(n2))
2201
+ return "money";
2202
+ if (/(shell|bash|exec|terminal|command|sandbox)/.test(n2))
2203
+ return "exec";
2204
+ if (/(cloudflare|vercel|netlify|modal|deploy|fly\.io|render|heroku|aws|gcp|azure)/.test(n2))
2205
+ return "deploy";
2206
+ if (/(github|gitlab|git|bitbucket)/.test(n2))
2207
+ return "write-remote";
2208
+ if (/(filesystem|file|fs|disk)/.test(n2))
2209
+ return "write-local";
2210
+ if (/(memory|supermemory|mem|obsidian|notion|airtable|coda|database|sql|store)/.test(n2))
2211
+ return "data";
2212
+ if (/(openrouter|ollama|openai|anthropic|llm|model|hugging)/.test(n2))
2213
+ return "model";
2214
+ if (/(exa|web|fetch|search|brave|browser|http|scrape)/.test(n2))
2215
+ return "network";
2216
+ return "network";
2217
+ }
2218
+ var REACH_RISK = {
2219
+ read: 0,
2220
+ model: 1,
2221
+ network: 1,
2222
+ data: 2,
2223
+ "write-local": 2,
2224
+ "write-remote": 3,
2225
+ deploy: 3,
2226
+ exec: 4,
2227
+ money: 4
2228
+ };
2229
+ function scoreBlast(reaches) {
2230
+ const reasons = [];
2231
+ const has = (r2) => reaches.includes(r2);
2232
+ if (has("money"))
2233
+ reasons.push("can move money");
2234
+ if (has("exec"))
2235
+ reasons.push("can run shell commands");
2236
+ if (has("deploy"))
2237
+ reasons.push("can deploy to production");
2238
+ if (has("write-remote"))
2239
+ reasons.push("can push to your remote repos");
2240
+ if (has("write-local"))
2241
+ reasons.push("can write your local files");
2242
+ if (has("data"))
2243
+ reasons.push("can read/write your stored data");
2244
+ const netCount = reaches.filter((r2) => r2 === "network" || r2 === "model").length;
2245
+ if (netCount >= 3)
2246
+ reasons.push(`reaches ${netCount} external services`);
2247
+ const max = reaches.reduce((m2, r2) => Math.max(m2, REACH_RISK[r2]), 0);
2248
+ let radius = "LOW";
2249
+ if (max >= 4)
2250
+ radius = "CRITICAL";
2251
+ else if (max >= 3)
2252
+ radius = "HIGH";
2253
+ else if (max >= 2)
2254
+ radius = "MEDIUM";
2255
+ return { radius, reasons };
2256
+ }
2257
+ function readJson(path) {
2258
+ try {
2259
+ return JSON.parse(readFileSync(path, "utf-8"));
2260
+ } catch {
2261
+ return null;
1961
2262
  }
1962
- const geminiSkillsPath = join2(homeDirPath, ".gemini", "skills");
1963
- if (existsSync(geminiSkillsPath)) {
1964
- try {
1965
- const skills = readdirSync(geminiSkillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
1966
- for (const skill of skills) {
1967
- if (!stats.skills.includes(skill))
1968
- stats.skills.push(skill);
1969
- }
1970
- } catch (e) {}
2263
+ }
2264
+ function countDir(path, ext = ".md") {
2265
+ try {
2266
+ return readdirSync(path).filter((f2) => f2.endsWith(ext)).length;
2267
+ } catch {
2268
+ return 0;
1971
2269
  }
1972
- const geminiMcpPath = join2(homeDirPath, ".gemini", "antigravity-cli", "mcp");
1973
- if (existsSync(geminiMcpPath)) {
2270
+ }
2271
+ async function getCapabilitiesStats(repoPath = process.cwd(), homeDirPath = homedir3()) {
2272
+ const mcpNames = new Set;
2273
+ for (const cfg of [
2274
+ join3(homeDirPath, ".claude.json"),
2275
+ join3(homeDirPath, ".claude", "settings.json"),
2276
+ join3(homeDirPath, ".cursor", "mcp.json"),
2277
+ join3(homeDirPath, ".gemini", "config", "mcp_config.json"),
2278
+ join3(homeDirPath, ".gemini", "settings.json"),
2279
+ join3(repoPath, ".mcp.json"),
2280
+ join3(repoPath, ".cursor", "mcp.json"),
2281
+ join3(repoPath, ".claude", "settings.json")
2282
+ ]) {
2283
+ const j = readJson(cfg);
2284
+ if (j?.mcpServers)
2285
+ Object.keys(j.mcpServers).forEach((k) => mcpNames.add(k));
2286
+ }
2287
+ const geminiMcp = join3(homeDirPath, ".gemini", "antigravity-cli", "mcp");
2288
+ if (existsSync2(geminiMcp)) {
1974
2289
  try {
1975
- const mcps = readdirSync(geminiMcpPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
1976
- stats.mcps.push(...mcps);
1977
- } catch (e) {}
2290
+ readdirSync(geminiMcp, { withFileTypes: true }).filter((d) => d.isDirectory()).forEach((d) => mcpNames.add(d.name));
2291
+ } catch {}
1978
2292
  }
1979
- const claudeSettingsPath = join2(homeDirPath, ".claude", "settings.json");
1980
- if (existsSync(claudeSettingsPath)) {
1981
- try {
1982
- const claudeSettings = __require(claudeSettingsPath);
1983
- if (claudeSettings.enabledPlugins) {
1984
- Object.keys(claudeSettings.enabledPlugins).forEach((plugin) => {
1985
- if (claudeSettings.enabledPlugins[plugin] && !stats.mcps.includes(plugin)) {
1986
- stats.mcps.push(`plugin:${plugin}`);
1987
- }
2293
+ const mcps = [...mcpNames].map((name) => ({ name, reach: classifyReach(name) }));
2294
+ const skills = [];
2295
+ for (const p2 of [join3(repoPath, ".agents", "skills"), join3(homeDirPath, ".claude", "skills"), join3(homeDirPath, ".gemini", "skills")]) {
2296
+ if (existsSync2(p2)) {
2297
+ try {
2298
+ readdirSync(p2, { withFileTypes: true }).filter((d) => d.isDirectory()).forEach((d) => {
2299
+ if (!skills.includes(d.name))
2300
+ skills.push(d.name);
1988
2301
  });
1989
- }
1990
- } catch (e) {}
2302
+ } catch {}
2303
+ }
1991
2304
  }
1992
- return stats;
2305
+ const subagents = countDir(join3(homeDirPath, ".claude", "agents")) + countDir(join3(repoPath, ".claude", "agents"));
2306
+ const hooks = [];
2307
+ for (const cfg of [join3(homeDirPath, ".claude", "settings.json"), join3(repoPath, ".claude", "settings.json")]) {
2308
+ const j = readJson(cfg);
2309
+ if (j?.hooks)
2310
+ Object.keys(j.hooks).forEach((k) => {
2311
+ if (!hooks.includes(k))
2312
+ hooks.push(k);
2313
+ });
2314
+ }
2315
+ const hasOrchestration = existsSync2(join3(repoPath, "AGENTS.md")) || existsSync2(join3(repoPath, ".mcp.json"));
2316
+ const { radius, reasons } = scoreBlast(mcps.map((m2) => m2.reach));
2317
+ return { mcps, skills, subagents, hooks, hasOrchestration, blastRadius: radius, blastReasons: reasons };
2318
+ }
2319
+
2320
+ // src/insights.ts
2321
+ var RANK = { critical: 0, warn: 1, info: 2, good: 3 };
2322
+ function deriveInsights({ authorship, carbon, caps, policyCap = 0.7 }) {
2323
+ const out = [];
2324
+ const ai = authorship ? authorship.ratio : null;
2325
+ const cachePct = carbon && carbon.totalTokens ? carbon.cacheReadTokens / carbon.totalTokens * 100 : null;
2326
+ const blast = caps ? caps.blastRadius : null;
2327
+ const writeOrDeploy = caps ? caps.mcps.filter((m2) => ["money", "exec", "deploy", "write-remote", "write-local"].includes(m2.reach)).length : 0;
2328
+ const heavyTokens = carbon ? carbon.totalTokens > 1e6 : false;
2329
+ if (ai !== null && ai > 0.7 && (blast === "HIGH" || blast === "CRITICAL")) {
2330
+ out.push({
2331
+ severity: "critical",
2332
+ title: "High reliance + high reach",
2333
+ detail: `AI wrote ${(ai * 100).toFixed(0)}% here and your agents can ${writeOrDeploy ? "write/deploy" : "reach external services"}. You may not own code that can ship to prod.`,
2334
+ action: "Review the core paths yourself before delegating more this session."
2335
+ });
2336
+ } else if (ai !== null && ai > 0.7) {
2337
+ out.push({
2338
+ severity: "warn",
2339
+ title: "You are mostly reviewing, not writing",
2340
+ detail: `AI wrote ${(ai * 100).toFixed(0)}% of recent commits — you risk losing the skill to debug it unaided.`,
2341
+ action: "Read the AI-written code through, or hand-write the next core change."
2342
+ });
2343
+ }
2344
+ if (ai !== null && ai < 0.1 && heavyTokens) {
2345
+ out.push({
2346
+ severity: "info",
2347
+ title: "Low AI% may be misleading",
2348
+ detail: "Heavy token use but few AI-tagged commits — your agent probably is not writing Co-Authored-By trailers.",
2349
+ action: "Treat the authorship number as a floor, not the truth, until trailers are on."
2350
+ });
2351
+ }
2352
+ if (caps && (blast === "CRITICAL" || blast === "HIGH")) {
2353
+ out.push({
2354
+ severity: blast === "CRITICAL" ? "critical" : "warn",
2355
+ title: `Blast radius ${blast}`,
2356
+ detail: `If an agent (or a prompt injection) drives your tools, it ${caps.blastReasons.slice(0, 2).join(" and ") || "has broad reach"}.`,
2357
+ action: "Disable the write/deploy MCP tools you do not need this session."
2358
+ });
2359
+ }
2360
+ if (cachePct !== null && cachePct > 80) {
2361
+ out.push({
2362
+ severity: "warn",
2363
+ title: "Most of your spend is re-sent context",
2364
+ detail: `${cachePct.toFixed(0)}% of your tokens just re-read old context — that is most of the bill, not new work.`,
2365
+ action: "Start fresh sessions for new tasks; keep context tight."
2366
+ });
2367
+ }
2368
+ if (ai !== null && ai > policyCap) {
2369
+ out.push({
2370
+ severity: "warn",
2371
+ title: "Over your AI-authorship limit",
2372
+ detail: `AI authorship is ${(ai * 100).toFixed(0)}%, over your ${(policyCap * 100).toFixed(0)}% limit.`,
2373
+ action: "Either raise the cap deliberately, or write the next change yourself."
2374
+ });
2375
+ }
2376
+ if (out.length === 0) {
2377
+ out.push({
2378
+ severity: "good",
2379
+ title: "Low risk",
2380
+ detail: ai !== null ? `You wrote most of this (${(100 - ai * 100).toFixed(0)}%) and your agents have limited reach.` : "No AI logs or git history found to flag.",
2381
+ action: "Carry on — re-run before your next big delegation."
2382
+ });
2383
+ }
2384
+ return out.sort((a2, b2) => RANK[a2.severity] - RANK[b2.severity]);
1993
2385
  }
1994
2386
 
1995
2387
  // src/cli.ts
1996
- import { writeFileSync, readFileSync as readFileSync2, chmodSync, existsSync as existsSync3 } from "fs";
2388
+ init_economics();
2389
+
2390
+ // src/aggregate.ts
2391
+ import { readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
1997
2392
  import { join as join4 } from "path";
2393
+ var BLAST_ORDER = ["LOW", "MEDIUM", "HIGH", "CRITICAL"];
2394
+ function aggregateDir(dir) {
2395
+ const files = readdirSync2(dir).filter((f2) => f2.endsWith(".json"));
2396
+ const audits = [];
2397
+ for (const f2 of files) {
2398
+ try {
2399
+ const j = JSON.parse(readFileSync2(join4(dir, f2), "utf-8"));
2400
+ if (j?.tool === "outlier")
2401
+ audits.push(j);
2402
+ } catch {}
2403
+ }
2404
+ const aiPcts = audits.map((a2) => a2.authorship?.aiPercent).filter((x) => typeof x === "number");
2405
+ const spends = audits.map((a2) => a2.cost?.estUsd || 0);
2406
+ const blasts = audits.map((a2) => a2.reach?.blastRadius).filter(Boolean);
2407
+ const overs = audits.filter((a2) => a2.policy?.status === "over").length;
2408
+ const writeDeploy = audits.reduce((s, a2) => s + (a2.reach?.writeOrDeployCount || 0), 0);
2409
+ const worst = blasts.reduce((m2, b2) => BLAST_ORDER.indexOf(b2) > BLAST_ORDER.indexOf(m2) ? b2 : m2, "LOW");
2410
+ const notes = [];
2411
+ if (aiPcts.length && Math.max(...aiPcts) > 70)
2412
+ notes.push("At least one developer is over 70% AI authorship.");
2413
+ if (worst === "HIGH" || worst === "CRITICAL")
2414
+ notes.push(`Worst-case agent blast radius across the team is ${worst}.`);
2415
+ if (overs > 0)
2416
+ notes.push(`${overs} developer(s) over their AI-authorship limit.`);
2417
+ if (audits.length === 0)
2418
+ notes.push("No outlier --json files found in this folder.");
2419
+ return {
2420
+ developers: audits.length,
2421
+ avgAiPercent: aiPcts.length ? +(aiPcts.reduce((a2, b2) => a2 + b2, 0) / aiPcts.length).toFixed(1) : null,
2422
+ maxAiPercent: aiPcts.length ? Math.max(...aiPcts) : null,
2423
+ totalEstUsd: +spends.reduce((a2, b2) => a2 + b2, 0).toFixed(2),
2424
+ worstBlastRadius: worst,
2425
+ overLimit: overs,
2426
+ reachWriteDeploy: writeDeploy,
2427
+ notes
2428
+ };
2429
+ }
2430
+
2431
+ // src/cli.ts
2432
+ import { writeFileSync, readFileSync as readFileSync4, chmodSync, existsSync as existsSync4 } from "fs";
2433
+ import { join as join6 } from "path";
1998
2434
 
1999
2435
  // src/agent.ts
2000
2436
  import { spawnSync as spawnSync2 } from "child_process";
2001
- import { readFileSync, existsSync as existsSync2 } from "fs";
2002
- import { join as join3 } from "path";
2437
+ import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
2438
+ import { join as join5 } from "path";
2003
2439
  import os from "os";
2004
2440
  function detectAgent() {
2005
2441
  const agents = ["claude", "cursor", "aider", "hermes", "cody", "continue", "opencode", "gemini"];
2006
2442
  try {
2007
2443
  const home = os.homedir();
2008
- const historyFiles = [join3(home, ".zsh_history"), join3(home, ".bash_history")];
2444
+ const historyFiles = [join5(home, ".zsh_history"), join5(home, ".bash_history")];
2009
2445
  for (const file of historyFiles) {
2010
- if (existsSync2(file)) {
2011
- const content = readFileSync(file, "utf8");
2446
+ if (existsSync3(file)) {
2447
+ const content = readFileSync3(file, "utf8");
2012
2448
  const lines = content.split(`
2013
2449
  `).filter(Boolean).slice(-500).reverse();
2014
2450
  for (const line of lines) {
@@ -2045,6 +2481,116 @@ var ASCII_LOGO = `
2045
2481
  \\____/|_| |_| |_| |_| |_|___|_____|_| \\_\\
2046
2482
  `;
2047
2483
  var finalReceipt = "";
2484
+ function closeBox(s, W2 = 66) {
2485
+ const wide = new Set(["⚠", "\uD83D\uDED1", "✈", "\uD83C\uDF31", "\uD83D\uDCF8", "\uD83D\uDD2C", "\uD83D\uDCBE", "\uD83D\uDCA1", "✅", "❌", "\uD83D\uDE3E", "\uD83D\uDE00"]);
2486
+ const chW = (ch) => {
2487
+ const cp = ch.codePointAt(0);
2488
+ return cp >= 126976 || wide.has(ch) ? 2 : 1;
2489
+ };
2490
+ const rail = "\x1B[2m│\x1B[0m";
2491
+ const fit = (line, totalVis) => {
2492
+ const parts = line.split(/(\x1b\[[0-9;]*m)/);
2493
+ let out = "", vis = 0, cut = false;
2494
+ for (const p2 of parts) {
2495
+ if (/^\x1b\[/.test(p2)) {
2496
+ out += p2;
2497
+ continue;
2498
+ }
2499
+ for (const ch of p2) {
2500
+ const w = chW(ch);
2501
+ if (vis + w > totalVis - 1) {
2502
+ cut = true;
2503
+ break;
2504
+ }
2505
+ out += ch;
2506
+ vis += w;
2507
+ }
2508
+ if (cut)
2509
+ break;
2510
+ }
2511
+ if (cut) {
2512
+ out += "…";
2513
+ vis += 1;
2514
+ }
2515
+ return out + " ".repeat(Math.max(0, totalVis - vis)) + "\x1B[0m";
2516
+ };
2517
+ return s.split(`
2518
+ `).map((line) => {
2519
+ const plain = line.replace(/\x1b\[[0-9;]*m/g, "");
2520
+ if (/^\s*┌/.test(plain))
2521
+ return " \x1B[2m┌" + "─".repeat(W2) + "┐\x1B[0m";
2522
+ if (/^\s*├/.test(plain))
2523
+ return " \x1B[2m├" + "─".repeat(W2) + "┤\x1B[0m";
2524
+ if (/^\s*└/.test(plain))
2525
+ return " \x1B[2m└" + "─".repeat(W2) + "┘\x1B[0m";
2526
+ if (/^\s*│/.test(plain))
2527
+ return fit(line, 2 + W2) + rail;
2528
+ return line;
2529
+ }).join(`
2530
+ `);
2531
+ }
2532
+ async function emitJson() {
2533
+ const pkg = require_package();
2534
+ const [gitStats, carbon, caps] = await Promise.all([
2535
+ getAuthorshipStats().catch(() => null),
2536
+ getCarbonStats().catch(() => null),
2537
+ getCapabilitiesStats().catch(() => null)
2538
+ ]);
2539
+ const aiRatio = gitStats ? gitStats.ratio : 0;
2540
+ const cap = 0.7;
2541
+ const writeOrDeploy = caps ? caps.mcps.filter((m2) => ["money", "exec", "deploy", "write-remote", "write-local"].includes(m2.reach)).length : 0;
2542
+ const out = {
2543
+ tool: "outlier",
2544
+ version: pkg.version,
2545
+ repo: process.cwd().split("/").pop(),
2546
+ generatedAt: new Date().toISOString(),
2547
+ localFirst: true,
2548
+ authorship: gitStats ? {
2549
+ aiPercent: +(gitStats.ratio * 100).toFixed(1),
2550
+ aiRatio: gitStats.ratio,
2551
+ totalCommits: gitStats.total,
2552
+ aiCommits: gitStats.ai,
2553
+ nonMergePercent: +(gitStats.ratioNoMerges * 100).toFixed(1),
2554
+ provenance: "proxy",
2555
+ note: "git Co-Authored-By trailers; under-counts if the agent omits the trailer"
2556
+ } : null,
2557
+ cost: carbon ? {
2558
+ totalTokens: carbon.totalTokens,
2559
+ outputTokens: carbon.outputTokens,
2560
+ cacheReusePercent: carbon.totalTokens ? +(carbon.cacheReadTokens / carbon.totalTokens * 100).toFixed(1) : 0,
2561
+ estUsd: +carbon.estUsd.toFixed(2),
2562
+ costIsReal: carbon.costIsReal,
2563
+ provenance: carbon.tokenProvenance,
2564
+ source: carbon.sourceLabel
2565
+ } : null,
2566
+ carbon: carbon ? {
2567
+ energyKwh: +carbon.energyKwh.toFixed(4),
2568
+ co2Kg: +carbon.localCo2Kg.toFixed(4),
2569
+ region: carbon.localRegion,
2570
+ provenance: carbon.carbonProvenance,
2571
+ note: "counterfactual: cloud inference runs on the provider grid, not yours"
2572
+ } : null,
2573
+ reach: caps ? {
2574
+ blastRadius: caps.blastRadius,
2575
+ reasons: caps.blastReasons,
2576
+ toolCount: caps.mcps.length,
2577
+ writeOrDeployCount: writeOrDeploy,
2578
+ tools: caps.mcps,
2579
+ subagents: caps.subagents,
2580
+ hooks: caps.hooks,
2581
+ skills: caps.skills.length,
2582
+ orchestration: caps.hasOrchestration
2583
+ } : null,
2584
+ policy: {
2585
+ aiCapPercent: cap * 100,
2586
+ status: aiRatio > cap ? "over" : "within"
2587
+ },
2588
+ insights: deriveInsights({ authorship: gitStats, carbon, caps, policyCap: cap }),
2589
+ economics: projectEconomics({ aiRatio, estUsdSession: carbon ? carbon.estUsd : 0, teamSize: 1 })
2590
+ };
2591
+ process.stdout.write(JSON.stringify(out, null, 2) + `
2592
+ `);
2593
+ }
2048
2594
  async function runOnboarding() {
2049
2595
  console.log(import_picocolors.default.cyan(ASCII_LOGO));
2050
2596
  intro(import_picocolors.default.inverse(" outlier: Welcome "));
@@ -2066,18 +2612,18 @@ As agents write more of our code, we lose visibility into:
2066
2612
  cancel("Onboarding paused. Run outlier again when you are ready.");
2067
2613
  process.exit(0);
2068
2614
  }
2069
- const configPath = join4(os2.homedir(), ".outlier_config");
2615
+ const configPath = join6(os2.homedir(), ".outlier_config");
2070
2616
  writeFileSync(configPath, JSON.stringify({ onboarded: true, date: new Date().toISOString() }));
2071
2617
  }
2072
2618
  async function main() {
2073
2619
  let action = process.argv[2];
2074
2620
  if (action === "daily-greeting") {
2075
- const configPath2 = join4(os2.homedir(), ".outlier_config");
2621
+ const configPath2 = join6(os2.homedir(), ".outlier_config");
2076
2622
  const today = new Date().toISOString().split("T")[0];
2077
2623
  let alreadyRun = false;
2078
- if (existsSync3(configPath2)) {
2624
+ if (existsSync4(configPath2)) {
2079
2625
  try {
2080
- const cfg = JSON.parse(readFileSync2(configPath2, "utf8"));
2626
+ const cfg = JSON.parse(readFileSync4(configPath2, "utf8"));
2081
2627
  if (cfg.lastGreetingDate === today) {
2082
2628
  alreadyRun = true;
2083
2629
  } else {
@@ -2088,7 +2634,17 @@ async function main() {
2088
2634
  }
2089
2635
  if (alreadyRun)
2090
2636
  process.exit(0);
2091
- action = "status";
2637
+ const g2 = await getAuthorshipStats().catch(() => null);
2638
+ const cp = await getCapabilitiesStats().catch(() => null);
2639
+ const aiP = g2 ? (g2.ratio * 100).toFixed(0) + "%" : "—";
2640
+ const br = cp ? cp.blastRadius : "—";
2641
+ const brc = br === "HIGH" || br === "CRITICAL" ? import_picocolors.default.red : br === "MEDIUM" ? import_picocolors.default.yellow : import_picocolors.default.green;
2642
+ console.log(`${import_picocolors.default.dim("[outlier]")} AI authorship ${import_picocolors.default.bold(aiP)} · agent reach ${brc(import_picocolors.default.bold(br))} ${import_picocolors.default.dim("· before you delegate, run: outlier preflight")}`);
2643
+ process.exit(0);
2644
+ }
2645
+ if (process.argv.includes("--json")) {
2646
+ await emitJson();
2647
+ process.exit(0);
2092
2648
  }
2093
2649
  console.log(import_picocolors.default.cyan(ASCII_LOGO));
2094
2650
  const pkg = require_package();
@@ -2102,8 +2658,10 @@ WHAT OUTLIER DOES`));
2102
2658
  `));
2103
2659
  console.log(import_picocolors.default.bold("COMMANDS:"));
2104
2660
  console.log(` ${import_picocolors.default.cyan("outlier")} Run the audit (the default — same as 'status')`);
2661
+ console.log(` ${import_picocolors.default.cyan("outlier preflight")} Quick briefing BEFORE you start an agent (reach + skill + spend)`);
2105
2662
  console.log(` ${import_picocolors.default.cyan("outlier status")} Full audit: who wrote the code, what it cost, your limit`);
2106
2663
  console.log(` ${import_picocolors.default.cyan("outlier status --save")} Save the audit to ./outlier-audit.txt`);
2664
+ console.log(` ${import_picocolors.default.cyan("outlier --json")} Machine-readable audit (for agents, CI, swarms)`);
2107
2665
  console.log(` ${import_picocolors.default.cyan("outlier authorship")} Just the AI-vs-human commit breakdown`);
2108
2666
  console.log(` ${import_picocolors.default.cyan("outlier carbon")} Just the token spend, cache waste & carbon`);
2109
2667
  console.log(` ${import_picocolors.default.cyan("outlier capabilities")} What tools & skills your agents can reach`);
@@ -2118,8 +2676,8 @@ WHAT OUTLIER DOES`));
2118
2676
  console.log(import_picocolors.default.dim("How it works → https://github.com/rosh100yx/outlier#how-it-works"));
2119
2677
  process.exit(0);
2120
2678
  }
2121
- const configPath = join4(os2.homedir(), ".outlier_config");
2122
- if (!existsSync3(configPath) && !action) {
2679
+ const configPath = join6(os2.homedir(), ".outlier_config");
2680
+ if (!existsSync4(configPath) && !action) {
2123
2681
  await runOnboarding();
2124
2682
  action = "status";
2125
2683
  }
@@ -2130,7 +2688,7 @@ WHAT OUTLIER DOES`));
2130
2688
  if (action === "init" || action === "uninit") {
2131
2689
  const shell = process.env.SHELL || "";
2132
2690
  const rcName = shell.includes("zsh") ? ".zshrc" : ".bashrc";
2133
- const rcPath = join4(os2.homedir(), rcName);
2691
+ const rcPath = join6(os2.homedir(), rcName);
2134
2692
  const START_MARKER = "# --- OUTLIER PRE-FLIGHT RITUAL START ---";
2135
2693
  const END_MARKER = "# --- OUTLIER PRE-FLIGHT RITUAL END ---";
2136
2694
  const BLOCK = `
@@ -2150,8 +2708,8 @@ ${END_MARKER}
2150
2708
  process.exit(0);
2151
2709
  }
2152
2710
  let content = "";
2153
- if (existsSync3(rcPath))
2154
- content = readFileSync2(rcPath, "utf8");
2711
+ if (existsSync4(rcPath))
2712
+ content = readFileSync4(rcPath, "utf8");
2155
2713
  if (content.includes(START_MARKER)) {
2156
2714
  note(`Outlier is already initialized in ${rcName}`);
2157
2715
  } else {
@@ -2160,8 +2718,8 @@ ${END_MARKER}
2160
2718
  }
2161
2719
  process.exit(0);
2162
2720
  } else if (action === "uninit") {
2163
- if (existsSync3(rcPath)) {
2164
- let content = readFileSync2(rcPath, "utf8");
2721
+ if (existsSync4(rcPath)) {
2722
+ let content = readFileSync4(rcPath, "utf8");
2165
2723
  if (content.includes(START_MARKER)) {
2166
2724
  const regex = new RegExp(`\\n?${START_MARKER}[\\s\\S]*?${END_MARKER}\\n?`, "g");
2167
2725
  content = content.replace(regex, `
@@ -2230,10 +2788,10 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2230
2788
  let carbon = null;
2231
2789
  let capabilities = null;
2232
2790
  let skipDelay = false;
2233
- const configPath2 = join4(os2.homedir(), ".outlier_config");
2234
- if (existsSync3(configPath2)) {
2791
+ const configPath2 = join6(os2.homedir(), ".outlier_config");
2792
+ if (existsSync4(configPath2)) {
2235
2793
  try {
2236
- const cfg = JSON.parse(readFileSync2(configPath2, "utf8"));
2794
+ const cfg = JSON.parse(readFileSync4(configPath2, "utf8"));
2237
2795
  if (cfg.seenNarration)
2238
2796
  skipDelay = true;
2239
2797
  } catch (e) {}
@@ -2271,7 +2829,7 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2271
2829
  await new Promise((r2) => setTimeout(r2, 600));
2272
2830
  if (!skipDelay) {
2273
2831
  try {
2274
- const cfg = existsSync3(configPath2) ? JSON.parse(readFileSync2(configPath2, "utf8")) : {};
2832
+ const cfg = existsSync4(configPath2) ? JSON.parse(readFileSync4(configPath2, "utf8")) : {};
2275
2833
  cfg.seenNarration = true;
2276
2834
  writeFileSync(configPath2, JSON.stringify(cfg));
2277
2835
  } catch (e) {}
@@ -2299,13 +2857,32 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2299
2857
  let cachePct = "0";
2300
2858
  let co2Str = "0.0kg";
2301
2859
  let regionStr = "Global Average";
2860
+ let sourceLabel = "no local AI logs found";
2861
+ let noData = true;
2302
2862
  if (carbon) {
2303
2863
  if (carbon.totalTokens > 0) {
2304
2864
  cachePct = (carbon.cacheReadTokens / carbon.totalTokens * 100).toFixed(1);
2865
+ noData = false;
2305
2866
  }
2306
2867
  co2Str = `${carbon.localCo2Kg.toFixed(2)}kg CO2`;
2307
2868
  regionStr = carbon.localRegion;
2869
+ sourceLabel = carbon.sourceLabel;
2308
2870
  }
2871
+ let reachStr = import_picocolors.default.dim("run: outlier capabilities");
2872
+ if (capabilities) {
2873
+ const rc = capabilities.blastRadius;
2874
+ const col = rc === "CRITICAL" || rc === "HIGH" ? import_picocolors.default.red : rc === "MEDIUM" ? import_picocolors.default.yellow : import_picocolors.default.green;
2875
+ const risky = capabilities.mcps.filter((m2) => ["money", "exec", "deploy", "write-remote", "write-local"].includes(m2.reach)).length;
2876
+ reachStr = `${col(import_picocolors.default.bold(rc))} · ${capabilities.mcps.length} tools` + (risky ? import_picocolors.default.dim(`, ${risky} can write/deploy`) : "");
2877
+ }
2878
+ const insights = deriveInsights({ authorship: gitStats, carbon, caps: capabilities, policyCap: 0.7 });
2879
+ const sevColor = (s2) => s2 === "critical" ? import_picocolors.default.red : s2 === "warn" ? import_picocolors.default.yellow : s2 === "good" ? import_picocolors.default.green : import_picocolors.default.cyan;
2880
+ const sevMark = (s2) => s2 === "critical" ? "✗" : s2 === "warn" ? "⚠" : s2 === "good" ? "✓" : "i";
2881
+ const insightLines = insights.slice(0, 2).map((ins) => ` ${import_picocolors.default.dim("│")} ${sevColor(ins.severity)(sevMark(ins.severity))} ${import_picocolors.default.bold(ins.title)}
2882
+ ` + ` ${import_picocolors.default.dim("│")} ${ins.detail.length > 56 ? ins.detail.slice(0, 55) + "…" : ins.detail}
2883
+ ` + ` ${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("→ " + ins.action)}`).join(`
2884
+ ${import_picocolors.default.dim("│")}
2885
+ `);
2309
2886
  const isDanger = gitStats && gitStats.ratio > 0.7;
2310
2887
  const verdictZone = isDanger ? import_picocolors.default.red("Mostly AI") : import_picocolors.default.green("You're driving");
2311
2888
  const verdictText = isDanger ? `AI wrote most of this. Read it through so you can
@@ -2353,15 +2930,23 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2353
2930
  ${import_picocolors.default.dim("│")} Tokens used ${import_picocolors.default.bold(totalTokensStr)}
2354
2931
  ${import_picocolors.default.dim("│")} Est. spend ${import_picocolors.default.bold(estUsdStr)}
2355
2932
  ${import_picocolors.default.dim("│")} Re-used context ${cacheBar} ${import_picocolors.default.bold(cachePct + "%")}
2356
- ${import_picocolors.default.dim("│")} Energy ${import_picocolors.default.bold(co2Str)} ${import_picocolors.default.dim(`(${regionStr} grid, rough)`)}
2933
+ ${import_picocolors.default.dim("│")} Energy ${import_picocolors.default.bold(co2Str)} ${import_picocolors.default.dim(`(${regionStr} grid)`)}
2934
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.dim(`Source: ${sourceLabel}`)}
2357
2935
  ${import_picocolors.default.dim("│")}
2358
2936
  ${import_picocolors.default.dim("│")} ${cacheVerdict} — ${cacheText.split(`
2359
2937
  `).join(`
2360
2938
  ` + import_picocolors.default.dim("│") + " ")}
2361
2939
  ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2940
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgCyan(import_picocolors.default.black(" WHAT YOUR AGENTS CAN REACH ")))}
2941
+ ${import_picocolors.default.dim("│")} Blast radius ${reachStr}
2942
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("Full map (deploy/push/write tools): outlier capabilities")}
2943
+ ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2362
2944
  ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgYellow(import_picocolors.default.black(" YOUR LIMIT ")))}
2363
2945
  ${import_picocolors.default.dim("│")} AI cap ${import_picocolors.default.bold("70%")} ${import_picocolors.default.dim("· change with: outlier policy")}
2364
2946
  ${import_picocolors.default.dim("│")} Status ${policyStatus} ${import_picocolors.default.dim("·")} ${policyAction}
2947
+ ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2948
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgGreen(import_picocolors.default.black(" WHAT TO DO ")))}
2949
+ ${insightLines}
2365
2950
  ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2366
2951
  ${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("Numbers are local estimates — authorship is a proxy and")}
2367
2952
  ${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("carbon is rough. How it works: outlier --help")}
@@ -2375,27 +2960,93 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2375
2960
  console.error(import_picocolors.default.red(e.message));
2376
2961
  }
2377
2962
  } else if (action === "capabilities") {
2378
- s.start("Auditing AI surface area (MCPs, Skills, Orchestrators)...");
2963
+ s.start("Mapping what your agents can reach...");
2379
2964
  try {
2380
2965
  const caps = await getCapabilitiesStats();
2381
- s.stop("Capabilities Scan Complete");
2382
- note(`Orchestration Policy: ${caps.hasOrchestration ? import_picocolors.default.green("Detected (AGENTS.md)") : import_picocolors.default.yellow("None")}
2966
+ s.stop("Reach map complete");
2967
+ const radiusColor = caps.blastRadius === "CRITICAL" ? import_picocolors.default.red : caps.blastRadius === "HIGH" ? import_picocolors.default.red : caps.blastRadius === "MEDIUM" ? import_picocolors.default.yellow : import_picocolors.default.green;
2968
+ const order = ["money", "exec", "deploy", "write-remote", "write-local", "data", "network", "model", "read"];
2969
+ const reachLabel = {
2970
+ money: "can move money",
2971
+ exec: "can run shell",
2972
+ deploy: "can deploy",
2973
+ "write-remote": "can push to repos",
2974
+ "write-local": "can write files",
2975
+ data: "data stores",
2976
+ network: "network",
2977
+ model: "models",
2978
+ read: "read-only"
2979
+ };
2980
+ const riskyReaches = new Set(["money", "exec", "deploy", "write-remote", "write-local"]);
2981
+ const toolLines = caps.mcps.length === 0 ? " None detected" : order.filter((r2) => caps.mcps.some((m2) => m2.reach === r2)).map((r2) => {
2982
+ const names = caps.mcps.filter((m2) => m2.reach === r2).map((m2) => m2.name).join(", ");
2983
+ const tag = riskyReaches.has(r2) ? import_picocolors.default.red(`[${reachLabel[r2]}]`) : import_picocolors.default.dim(`[${reachLabel[r2]}]`);
2984
+ return ` ${tag} ${names}`;
2985
+ }).join(`
2986
+ `);
2987
+ note(`${import_picocolors.default.bold("BLAST RADIUS:")} ${radiusColor(import_picocolors.default.bold(caps.blastRadius))} ${import_picocolors.default.dim("— if an agent or a prompt injection drives your tools")}
2988
+ ${caps.blastReasons.length ? caps.blastReasons.map((r2) => ` ${import_picocolors.default.red("•")} ${r2}`).join(`
2989
+ `) : import_picocolors.default.green(" • read-only — limited reach")}
2383
2990
 
2384
- Active Skills (${caps.skills.length}):
2385
- ${caps.skills.length > 0 ? import_picocolors.default.cyan(caps.skills.map((s2) => ` • ${s2}`).join(`
2386
- `)) : " None"}
2991
+ ${import_picocolors.default.bold(`What your agents can reach (${caps.mcps.length} MCP tools):`)}
2992
+ ${toolLines}
2387
2993
 
2388
- Active MCP Servers (${caps.mcps.length}):
2389
- ${caps.mcps.length > 0 ? import_picocolors.default.magenta(caps.mcps.map((m2) => ` • ${m2}`).join(`
2390
- `)) : " None"}
2994
+ ${import_picocolors.default.bold("Automation & agents:")}
2995
+ Hooks that fire for you: ${caps.hooks.length ? import_picocolors.default.yellow(caps.hooks.join(", ")) : "none"}
2996
+ Sub-agents: ${caps.subagents} Skills: ${caps.skills.length} Orchestration policy: ${caps.hasOrchestration ? import_picocolors.default.green("yes") : import_picocolors.default.yellow("no")}
2391
2997
 
2392
- ${import_picocolors.default.bold("Governance Assessment:")}
2393
- This repository provides agents with ${caps.mcps.length} toolsets and ${caps.skills.length} skills.
2394
- ${caps.skills.length > 5 ? import_picocolors.default.red("⚠ High Surface Area: Ensure strict authorship review is enabled.") : import_picocolors.default.green("✓ Low Surface Area: Risk contained.")}`, "AI Capabilities Map");
2998
+ ${import_picocolors.default.dim("This is your attack surface. Fewer write/deploy tools per session = smaller blast radius.")}`, "Agent Reach & Blast Radius");
2395
2999
  } catch (e) {
2396
3000
  s.stop("Audit failed");
2397
3001
  console.error(import_picocolors.default.red(e.message));
2398
3002
  }
3003
+ } else if (action === "aggregate") {
3004
+ const dir = process.argv[3];
3005
+ if (!dir || !existsSync4(dir)) {
3006
+ console.error(import_picocolors.default.red("Usage: outlier aggregate <folder-of-json-audits>"));
3007
+ console.log(import_picocolors.default.dim(" Each dev: outlier --json > team/<name>.json then: outlier aggregate team/"));
3008
+ process.exit(1);
3009
+ }
3010
+ const r2 = aggregateDir(dir);
3011
+ note(`Developers: ${import_picocolors.default.bold(String(r2.developers))}
3012
+ Avg AI authorship: ${import_picocolors.default.bold(r2.avgAiPercent !== null ? r2.avgAiPercent + "%" : "—")} Max: ${r2.maxAiPercent !== null ? r2.maxAiPercent + "%" : "—"}
3013
+ Over their limit: ${r2.overLimit > 0 ? import_picocolors.default.red(String(r2.overLimit)) : import_picocolors.default.green("0")}
3014
+ Team spend (est): ${import_picocolors.default.bold("$" + r2.totalEstUsd)}
3015
+ Worst blast radius:${" "}${r2.worstBlastRadius === "HIGH" || r2.worstBlastRadius === "CRITICAL" ? import_picocolors.default.red(r2.worstBlastRadius) : import_picocolors.default.yellow(r2.worstBlastRadius)} (${r2.reachWriteDeploy} write/deploy tools across the team)
3016
+ ${r2.notes.length ? `
3017
+ ` + r2.notes.map((n2) => `${import_picocolors.default.yellow("•")} ${n2}`).join(`
3018
+ `) : ""}`, "Team Rollup (local-first — nothing was exported)");
3019
+ } else if (action === "preflight") {
3020
+ s.start("Pre-flight check...");
3021
+ const gitStats = await getAuthorshipStats().catch(() => null);
3022
+ const carbon = await getCarbonStats().catch(() => null);
3023
+ const caps = await getCapabilitiesStats().catch(() => null);
3024
+ s.stop("Ready for take-off");
3025
+ const aiPct = gitStats ? (gitStats.ratio * 100).toFixed(0) : "—";
3026
+ const youPct = gitStats ? (100 - gitStats.ratio * 100).toFixed(0) : "—";
3027
+ const blast = caps ? caps.blastRadius : "UNKNOWN";
3028
+ const blastCol = blast === "CRITICAL" || blast === "HIGH" ? import_picocolors.default.red : blast === "MEDIUM" ? import_picocolors.default.yellow : import_picocolors.default.green;
3029
+ const risky = caps ? caps.mcps.filter((m2) => ["money", "exec", "deploy", "write-remote", "write-local"].includes(m2.reach)).length : 0;
3030
+ const spend = carbon ? `$${carbon.estUsd.toFixed(0)}` : "—";
3031
+ const cachePct = carbon && carbon.totalTokens ? (carbon.cacheReadTokens / carbon.totalTokens * 100).toFixed(0) + "%" : "—";
3032
+ const insights = deriveInsights({ authorship: gitStats, carbon, caps, policyCap: 0.7 });
3033
+ const sevCol = (sv) => sv === "critical" ? import_picocolors.default.red : sv === "warn" ? import_picocolors.default.yellow : sv === "good" ? import_picocolors.default.green : import_picocolors.default.cyan;
3034
+ const sevMk = (sv) => sv === "critical" ? "✗" : sv === "warn" ? "⚠" : sv === "good" ? "✓" : "i";
3035
+ const actionLines = insights.slice(0, 3).map((ins) => ` ${sevCol(ins.severity)(sevMk(ins.severity))} ${import_picocolors.default.cyan("→")} ${ins.action}`).join(`
3036
+ `);
3037
+ console.log("");
3038
+ console.log(import_picocolors.default.bold(import_picocolors.default.cyan(" ✈ PRE-FLIGHT")) + import_picocolors.default.dim(` · ${process.cwd().split("/").pop()}`));
3039
+ console.log(import_picocolors.default.dim(" ────────────────────────────────────────────────────"));
3040
+ console.log(` ${import_picocolors.default.bold("Reach")} ${blastCol(import_picocolors.default.bold(blast))}` + (caps ? import_picocolors.default.dim(` · ${caps.mcps.length} tools, ${risky} can write/deploy`) : ""));
3041
+ console.log(` ${import_picocolors.default.bold("Skill")} AI wrote ${import_picocolors.default.bold(aiPct + "%")} · you own ${import_picocolors.default.bold(youPct + "%")}`);
3042
+ console.log(` ${import_picocolors.default.bold("Spend")} ${import_picocolors.default.bold(spend)} · ${cachePct} re-sent context`);
3043
+ console.log("");
3044
+ console.log(import_picocolors.default.bold(" Before you delegate:"));
3045
+ console.log(actionLines);
3046
+ console.log("");
3047
+ const agent = detectAgent();
3048
+ console.log(import_picocolors.default.bold(import_picocolors.default.magenta(" ✓ Ready? ")) + "Start your session: " + import_picocolors.default.bold(agent || "your AI agent"));
3049
+ console.log("");
2399
3050
  } else if (action === "policy") {
2400
3051
  const tier = await select({
2401
3052
  message: "Select the governance tier to configure:",
@@ -2425,8 +3076,8 @@ ${caps.skills.length > 5 ? import_picocolors.default.red("⚠ High Surface Area:
2425
3076
  process.exit(0);
2426
3077
  }
2427
3078
  s.start(`Applying ${tier} policy guardrails...`);
2428
- const gitDir = join4(process.cwd(), ".git");
2429
- const isRepo = existsSync3(gitDir);
3079
+ const gitDir = join6(process.cwd(), ".git");
3080
+ const isRepo = existsSync4(gitDir);
2430
3081
  if (!isRepo) {
2431
3082
  console.error(import_picocolors.default.red("Must be run inside a git repository"));
2432
3083
  process.exit(1);
@@ -2434,8 +3085,8 @@ ${caps.skills.length > 5 ? import_picocolors.default.red("⚠ High Surface Area:
2434
3085
  const isStrict = process.argv.includes("--strict");
2435
3086
  const bouncerMsg = isStrict ? `echo "⚠️ outlier policy warning: AI authorship ($CURRENT_RATIO%) exceeds threshold ($MAX_RATIO%)"` : `echo "\uD83D\uDEE1️ Outlier Bouncer: Repository AI-generation ($CURRENT_RATIO%) exceeds your defined mastery threshold ($MAX_RATIO%)."
2436
3087
  echo "Take a moment to review your recent architectural decisions. Ensure you still understand the system."`;
2437
- const hookPath = join4(gitDir, "hooks", "pre-commit");
2438
- if (existsSync3(hookPath)) {
3088
+ const hookPath = join6(gitDir, "hooks", "pre-commit");
3089
+ if (existsSync4(hookPath)) {
2439
3090
  const { copyFileSync } = __require("fs");
2440
3091
  copyFileSync(hookPath, `${hookPath}.backup`);
2441
3092
  }
@@ -2466,16 +3117,31 @@ Rule 1: ${import_picocolors.default.green(`AI Authorship must not exceed $
2466
3117
  Rule 2: ${import_picocolors.default.green("Require human review on consecutive high-AI sprints")}
2467
3118
  Enforcement: ${import_picocolors.default.cyan("Local pre-commit hook installed (backup created)")}`, "Active Governance Policy");
2468
3119
  } else if (tier === "regulatory") {
2469
- s.start("Generating Regulatory Compliance Audit (Decree 142)...");
2470
- await new Promise((resolve) => setTimeout(resolve, 1200));
2471
- const reportPath = join4(process.cwd(), "outlier-audit-report.jsonl");
2472
- writeFileSync(reportPath, JSON.stringify({ timestamp: new Date().toISOString(), status: "PREVIEW", policy: "Decree 142", simulatedOversight: true }) + `
3120
+ s.start("Generating human-oversight audit record (Decree 142)...");
3121
+ const gitStats = await getAuthorshipStats().catch(() => null);
3122
+ const caps = await getCapabilitiesStats().catch(() => null);
3123
+ const humanReviewRate = gitStats ? +(1 - gitStats.ratio).toFixed(3) : null;
3124
+ const oversightOk = humanReviewRate !== null && humanReviewRate >= 0.3;
3125
+ const record = {
3126
+ timestamp: new Date().toISOString(),
3127
+ policy: "Vietnam Decree 142/2026 — human oversight of high-risk AI",
3128
+ repo: process.cwd().split("/").pop(),
3129
+ humanAuthorshipRate: humanReviewRate,
3130
+ aiAuthorshipRate: gitStats ? +gitStats.ratio.toFixed(3) : null,
3131
+ humanOversight: oversightOk ? "present" : "insufficient",
3132
+ agentBlastRadius: caps ? caps.blastRadius : "unknown",
3133
+ dataExported: false,
3134
+ note: "Derived from local git history only. No code, prompts, or citizen data leave the machine. Authorship is a proxy for human oversight."
3135
+ };
3136
+ const reportPath = join6(process.cwd(), "outlier-audit-report.jsonl");
3137
+ writeFileSync(reportPath, JSON.stringify(record) + `
2473
3138
  `);
2474
- s.stop("Audit Generated");
2475
- note(`Jurisdiction: ${import_picocolors.default.bold("Vietnam (Decree 142)")}
2476
- Status: ${import_picocolors.default.green("Compliant - Human oversight logged locally")}
2477
- Privacy: ${import_picocolors.default.green("Preserved - No citizen data exported")}
2478
- Artifact: ${import_picocolors.default.cyan(reportPath)}`, "Regulatory Compliance");
3139
+ s.stop("Audit record written");
3140
+ note(`Jurisdiction: ${import_picocolors.default.bold("Vietnam (Decree 142/2026)")}
3141
+ Human oversight: ${oversightOk ? import_picocolors.default.green("present") : import_picocolors.default.red("insufficient")} ${import_picocolors.default.dim(`(${humanReviewRate !== null ? (humanReviewRate * 100).toFixed(0) + "% human-authored" : "no git history"})`)}
3142
+ Agent reach: ${caps ? caps.blastRadius : "unknown"}
3143
+ Privacy: ${import_picocolors.default.green("preserved — nothing exported")}
3144
+ Artifact: ${import_picocolors.default.cyan(reportPath)}`, "Human-Oversight Audit Record");
2479
3145
  }
2480
3146
  } else if (action === "participate") {
2481
3147
  s.start("Connecting to the Outlier research project...");
@@ -2547,6 +3213,28 @@ ${import_picocolors.default.bold("Submit here (and drop your screenshot!):")} ${
2547
3213
  ■ Next 5-10 Years (The 1M+ LOC Crisis)`));
2548
3214
  console.log(` When an agent introduces a fatal state bug in a monolithic architecture, human reviewers will lack the muscle memory to debug it. Outlier measures this exact sovereignty erosion.
2549
3215
  `);
3216
+ const gitStats = await getAuthorshipStats().catch(() => null);
3217
+ const carbon = await getCarbonStats().catch(() => null);
3218
+ if (gitStats || carbon) {
3219
+ const { projectEconomics: projectEconomics2 } = await Promise.resolve().then(() => (init_economics(), exports_economics));
3220
+ const teamSize = (() => {
3221
+ const i2 = process.argv.indexOf("--team");
3222
+ return i2 > -1 ? parseInt(process.argv[i2 + 1] || "1") || 1 : 1;
3223
+ })();
3224
+ const econ = projectEconomics2({
3225
+ aiRatio: gitStats ? gitStats.ratio : 0,
3226
+ estUsdSession: carbon ? carbon.estUsd : 0,
3227
+ teamSize
3228
+ });
3229
+ console.log(import_picocolors.default.bold(import_picocolors.default.bgMagenta(" THE MACRO SHADOW ")) + import_picocolors.default.dim(` (team of ${teamSize} — set with --team N)`));
3230
+ for (const p2 of econ.projections) {
3231
+ console.log(` ${import_picocolors.default.bold(p2.label.padEnd(20))} ${import_picocolors.default.cyan(p2.value)}`);
3232
+ console.log(` ${import_picocolors.default.dim(" " + p2.note)}`);
3233
+ }
3234
+ console.log(`
3235
+ ` + import_picocolors.default.dim(" " + econ.assumptions) + `
3236
+ `);
3237
+ }
2550
3238
  } else if (action === "knowledge") {
2551
3239
  console.log(`
2552
3240
  ` + import_picocolors.default.bold(import_picocolors.default.bgBlue(" CORE LITERATURE & REFERENCES ")) + `
@@ -2560,12 +3248,13 @@ Read the full academic foundation at: ${import_picocolors.default.underline("htt
2560
3248
  }
2561
3249
  outro("Done — nothing left your machine. (How it works: outlier --help)");
2562
3250
  if (typeof finalReceipt !== "undefined" && finalReceipt) {
2563
- console.log(finalReceipt);
3251
+ const boxed = closeBox(finalReceipt);
3252
+ console.log(boxed);
2564
3253
  if (process.argv.includes("--save")) {
2565
3254
  const stripAnsi = (s2) => s2.replace(/\x1b\[[0-9;]*m/g, "");
2566
- const savePath = join4(process.cwd(), "outlier-audit.txt");
3255
+ const savePath = join6(process.cwd(), "outlier-audit.txt");
2567
3256
  try {
2568
- writeFileSync(savePath, stripAnsi(finalReceipt).trimStart() + `
3257
+ writeFileSync(savePath, stripAnsi(boxed).trimStart() + `
2569
3258
  `);
2570
3259
  console.log(import_picocolors.default.dim(`
2571
3260
  \uD83D\uDCBE Saved to ${savePath}`));