@rosh100yx/outlier 0.4.22 → 0.4.24

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
@@ -165,7 +165,7 @@ var require_picocolors = __commonJS((exports, module) => {
165
165
  var require_package = __commonJS((exports, module) => {
166
166
  module.exports = {
167
167
  name: "@rosh100yx/outlier",
168
- version: "0.4.22",
168
+ version: "0.4.24",
169
169
  description: "AI Code Governance & Capability Auditing for the Terminal. Measures AI reliance, context waste, and enforces local CI/CD policies.",
170
170
  bin: {
171
171
  outlier: "bin/outlier.js"
@@ -1821,12 +1821,12 @@ class ClaudeLogParser {
1821
1821
  try {
1822
1822
  await access(logPath);
1823
1823
  } catch {
1824
- return { total: 0, output: 0, cache: 0, sessions: 0 };
1824
+ return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0 };
1825
1825
  }
1826
1826
  const text2 = await readFile(logPath, "utf-8");
1827
1827
  const lines = text2.trim().split(`
1828
1828
  `).filter((l2) => l2.length > 0);
1829
- let total = 0, output = 0, cache = 0;
1829
+ let total = 0, output = 0, cache = 0, cost = 0;
1830
1830
  const sessions = new Set;
1831
1831
  for (const line of lines) {
1832
1832
  try {
@@ -1834,19 +1834,24 @@ class ClaudeLogParser {
1834
1834
  total += data.total_tokens || 0;
1835
1835
  output += data.output_tokens || 0;
1836
1836
  cache += data.cache_read || 0;
1837
+ cost += data.cost_usd || 0;
1837
1838
  if (data.session_id)
1838
1839
  sessions.add(data.session_id);
1839
1840
  } catch (e) {}
1840
1841
  }
1841
- return { total, output, cache, sessions: sessions.size };
1842
+ return { total, output, cache, sessions: sessions.size, cost };
1842
1843
  }
1843
1844
  }
1844
1845
 
1845
1846
  class CursorLogParser {
1846
1847
  async parse() {
1847
- return { total: 0, output: 0, cache: 0, sessions: 0 };
1848
+ return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0 };
1848
1849
  }
1849
1850
  }
1851
+ function estimateUsd(output, cacheRead, total) {
1852
+ const otherInput = Math.max(0, total - output - cacheRead);
1853
+ return output / 1e6 * 9 + cacheRead / 1e6 * 0.3 + otherInput / 1e6 * 3;
1854
+ }
1850
1855
  function getLocalGridFactor() {
1851
1856
  try {
1852
1857
  const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -1865,16 +1870,19 @@ function getLocalGridFactor() {
1865
1870
  }
1866
1871
  async function getCarbonStats() {
1867
1872
  const parsers = [new ClaudeLogParser, new CursorLogParser];
1868
- let totalTokens = 0, outputTokens = 0, cacheReadTokens = 0, sessions = 0;
1873
+ let totalTokens = 0, outputTokens = 0, cacheReadTokens = 0, sessions = 0, loggedCost = 0;
1869
1874
  for (const parser of parsers) {
1870
1875
  const stats = await parser.parse();
1871
1876
  totalTokens += stats.total;
1872
1877
  outputTokens += stats.output;
1873
1878
  cacheReadTokens += stats.cache;
1874
1879
  sessions += stats.sessions;
1880
+ loggedCost += stats.cost;
1875
1881
  }
1876
1882
  const energyKwh = outputTokens / 1e6 * 0.662;
1877
1883
  const localGrid = getLocalGridFactor();
1884
+ const costIsReal = loggedCost > 0;
1885
+ const estUsd = costIsReal ? loggedCost : estimateUsd(outputTokens, cacheReadTokens, totalTokens);
1878
1886
  return {
1879
1887
  totalTokens,
1880
1888
  outputTokens,
@@ -1884,7 +1892,9 @@ async function getCarbonStats() {
1884
1892
  co2KgFrance: energyKwh * grid_factors_default.france / 1000,
1885
1893
  localCo2Kg: energyKwh * localGrid.factor / 1000,
1886
1894
  localRegion: localGrid.region,
1887
- sessions
1895
+ sessions,
1896
+ estUsd,
1897
+ costIsReal
1888
1898
  };
1889
1899
  }
1890
1900
 
@@ -1995,7 +2005,6 @@ var ASCII_LOGO = `
1995
2005
  `;
1996
2006
  var finalReceipt = "";
1997
2007
  async function runOnboarding() {
1998
- console.clear();
1999
2008
  console.log(import_picocolors.default.cyan(ASCII_LOGO));
2000
2009
  intro(import_picocolors.default.inverse(" outlier: Welcome "));
2001
2010
  note(`Outlier is a local-first Policy Engine & Governance Framework for AI Engineering.
@@ -2040,7 +2049,6 @@ async function main() {
2040
2049
  process.exit(0);
2041
2050
  action = "status";
2042
2051
  }
2043
- console.clear();
2044
2052
  console.log(import_picocolors.default.cyan(ASCII_LOGO));
2045
2053
  const pkg = require_package();
2046
2054
  console.log(import_picocolors.default.dim(` Outlier v${pkg.version} · AI Code Reliance & Telemetry Engine
@@ -2230,29 +2238,10 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2230
2238
  try {
2231
2239
  let authPct = "0%";
2232
2240
  let ruleFailures = 0;
2233
- let authWarning = "";
2234
- let wittyRemark = isStrict ? "" : "No git history (・_・ヾ";
2235
- let mentorString = "";
2236
2241
  if (gitStats) {
2237
2242
  authPct = `${(gitStats.ratio * 100).toFixed(1)}%`;
2238
- if (!isStrict) {
2239
- if (gitStats.ratio < 0.1)
2240
- wittyRemark = "Artisan, hand-crafted code. Very 2019 of you (=^ ◡ ^=)";
2241
- else if (gitStats.ratio < 0.6)
2242
- wittyRemark = "A true centaur. Half human, half matrix (=`ω´=)";
2243
- else if (gitStats.ratio < 0.95)
2244
- wittyRemark = "Orchestrating the swarm. You are the manager now (ФДФ)";
2245
- else
2246
- wittyRemark = "100% Cybernetic. Codebase goes brrrrr (=ಠᆽಠ=)";
2247
- }
2248
- if (gitStats.ratio > 0.7) {
2249
- authWarning = import_picocolors.default.red(isStrict ? `⚠ High Risk Surface: ${authPct} AI-generated. Human review required.` : `⚠ Mentoring Emergency: ${authPct} AI-generated. High risk of skill atrophy.`);
2250
- if (!isStrict) {
2251
- mentorString = `
2252
- mentor: ${import_picocolors.default.blue("\uD83D\uDCA1 Architecture Challenge Pending (See Git Hook)")}`;
2253
- }
2243
+ if (gitStats.ratio > 0.7)
2254
2244
  ruleFailures++;
2255
- }
2256
2245
  }
2257
2246
  let cachePct = "0";
2258
2247
  let co2Str = "0.0kg";
@@ -2264,39 +2253,23 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
2264
2253
  co2Str = `${carbon.localCo2Kg.toFixed(2)}kg CO2`;
2265
2254
  regionStr = carbon.localRegion;
2266
2255
  }
2267
- const vibeRow = !isStrict ? `
2268
- vibe: ${import_picocolors.default.italic(wittyRemark)}` : "";
2269
- const capIcon = isStrict ? "" : "(Ф∇Ф) ";
2270
- const authIcon = isStrict ? "" : "(=^・ω・^=) ";
2271
- const costIcon = isStrict ? "" : "(O_O;) ";
2272
- const failIcon = isStrict ? "⚠" : "(=ಠᆽಠ=)";
2273
- const passIcon = isStrict ? "✓" : "(=^ ◡ ^=)";
2274
- note(`${capIcon}${import_picocolors.default.dim("[1] Capability Engine")} ${import_picocolors.default.cyan("▰▰▰▰▰▰▱▱▱▱")} ${import_picocolors.default.bold("Active")}
2275
- status: ${import_picocolors.default.green("✓ Configured")}
2276
- ${authIcon}${import_picocolors.default.dim("[2] AI Code Reliance")} ${import_picocolors.default.yellow("▰▰▰▰▰▰▰▰▱▱")} ${import_picocolors.default.bold(`${authPct} Reliance`)}${vibeRow}
2277
- gate: ${gitStats && gitStats.ratio <= 0.7 ? import_picocolors.default.green("✓ Human Mastery Sustained") : `${import_picocolors.default.red(`${failIcon} Deskilling Risk Detected`)} ${import_picocolors.default.red("⚠ Security Audit Required")}`}${mentorString}
2278
- ${costIcon}${import_picocolors.default.dim("[3] Tokenomics & Cost")} ${import_picocolors.default.magenta("▰▰▰▰▰▰▰▰▰▱")} ${import_picocolors.default.bold(`${cachePct}% Cache Bloat`)}
2279
- waste: ${import_picocolors.default.yellow(`⚠ ${cachePct}% of tokens are redundant context reads`)}
2280
- carbon: ${import_picocolors.default.green(`✓ ${co2Str} (Est. ${regionStr} Grid)`)}
2281
- ${import_picocolors.default.bold("Governance:")} ${ruleFailures > 0 ? import_picocolors.default.red(`${failIcon} ${ruleFailures + 1} policy failures`) : import_picocolors.default.green(`${passIcon} All clear`)}`, `${import_picocolors.default.bold("[outlier]")} ${5 - (ruleFailures + 1)}/5 policies • ${authWarning || import_picocolors.default.green(`${passIcon} safe surface`)} • ${co2Str}`);
2282
- const timestamp = new Date().toISOString().split("T")[0];
2283
2256
  const isDanger = gitStats && gitStats.ratio > 0.7;
2284
- const verdictZone = isDanger ? import_picocolors.default.red("DANGER ZONE") : import_picocolors.default.green("SAFE / SOVEREIGN");
2285
- const verdictText = isDanger ? `You are transitioning from 'Creator' to 'Reviewer'.
2286
- At this trajectory, you risk losing architectural
2287
- muscle memory on this codebase within 6 months.` : `You are maintaining strong architectural intimacy.
2288
- Your human judgement remains the primary driver
2289
- of logic in this system.`;
2257
+ const verdictZone = isDanger ? import_picocolors.default.red("Mostly AI") : import_picocolors.default.green("You're driving");
2258
+ const verdictText = isDanger ? `AI wrote most of this. Read it through so you can
2259
+ still debug it yourself when the agent isn't around.` : `You're still writing the core of this. Good —
2260
+ that's how you keep the skill.`;
2290
2261
  const isInefficient = parseFloat(cachePct) > 40;
2291
- const cacheVerdict = isInefficient ? import_picocolors.default.yellow("INEFFICIENT") : import_picocolors.default.green("EFFICIENT");
2292
- const cacheText = isInefficient ? `You are burning paid API tokens and excess compute
2293
- on files the agent isn't even touching.` : `Your token usage and human judgment are tightly
2294
- coupled. High signal-to-noise ratio.`;
2295
- const policyStatus = ruleFailures > 0 ? import_picocolors.default.red("BLOCKED \uD83D\uDED1 (Threshold Exceeded)") : import_picocolors.default.green("PASS ✅ (Within Threshold)");
2296
- const policyAction = ruleFailures > 0 ? "Triggering Mandatory Mentoring Scenario." : "No intervention required.";
2297
- const totalTokensStr = carbon ? (carbon.totalTokens / 1000).toFixed(1) + "k" : "0";
2298
- const humanSov = gitStats ? ((1 - gitStats.ratio) * 100).toFixed(1) + "%" : "100%";
2299
- const authorshipStr = authPct + (isDanger ? import_picocolors.default.red(" (High Reliance)") : import_picocolors.default.green(" (Healthy)"));
2262
+ const cacheVerdict = isInefficient ? import_picocolors.default.yellow("Lots of re-reads") : import_picocolors.default.green("Lean");
2263
+ const cacheText = isInefficient ? `Most of your tokens just re-send old context.
2264
+ It's normal for agents, but it's most of the bill.` : `Little wasted context. Your spend is mostly
2265
+ real work.`;
2266
+ const policyStatus = ruleFailures > 0 ? import_picocolors.default.red("Over your limit") : import_picocolors.default.green("Within limit");
2267
+ const policyAction = ruleFailures > 0 ? "Heads up only — nothing was blocked." : "Nothing to do.";
2268
+ const fmtTokens = (n2) => n2 >= 1e9 ? (n2 / 1e9).toFixed(1) + "B" : n2 >= 1e6 ? (n2 / 1e6).toFixed(1) + "M" : n2 >= 1000 ? (n2 / 1000).toFixed(1) + "k" : String(n2);
2269
+ const totalTokensStr = carbon ? fmtTokens(carbon.totalTokens) : "0";
2270
+ const estUsdStr = carbon ? "$" + carbon.estUsd.toFixed(2) + (carbon.costIsReal ? "" : import_picocolors.default.dim(" (rough)")) : import_picocolors.default.dim("n/a");
2271
+ const humanSov = gitStats ? ((1 - gitStats.ratio) * 100).toFixed(0) + "%" : "100%";
2272
+ const authorshipStr = import_picocolors.default.bold(authPct) + (isDanger ? import_picocolors.default.red(" AI-written") : import_picocolors.default.green(" AI-written"));
2300
2273
  const getProgressBar = (pct, length = 10) => {
2301
2274
  const filled = Math.max(0, Math.min(length, Math.round(pct / 100 * length)));
2302
2275
  return "▰".repeat(filled) + "▱".repeat(length - filled);
@@ -2311,38 +2284,33 @@ ${import_picocolors.default.bold("Governance:")} ${ruleFailures > 0 ? import_pic
2311
2284
  const repoName = process.cwd().split("/").pop() || "Unknown";
2312
2285
  finalReceipt = `
2313
2286
  ${import_picocolors.default.dim("┌────────────────────────────────────────────────────────")}
2314
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("█▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█")} ${import_picocolors.default.bold(":: THERMAL AUDIT RECEIPT")}
2315
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("█▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄")} ${import_picocolors.default.dim(`:: TIMESTAMP: ${dateStr}`)}
2287
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("█▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█")} ${import_picocolors.default.bold(":: CODE AUDIT")}
2288
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("█▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄")} ${import_picocolors.default.dim(`:: ${repoName} · ${dateStr}`)}
2316
2289
  ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2317
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgBlue(" [ COGNITIVE BUDGET ] "))}
2318
- ${import_picocolors.default.dim("│")} AI Authorship ................. ${aiBar} ${authorshipStr}
2319
- ${import_picocolors.default.dim("│")} Human Sovereignty ................. ${humanBar} ${humanSov}
2290
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgBlue(" WHO WROTE THE CODE "))}
2291
+ ${import_picocolors.default.dim("│")} AI ${aiBar} ${authorshipStr}
2292
+ ${import_picocolors.default.dim("│")} You ${humanBar} ${import_picocolors.default.bold(humanSov)}
2320
2293
  ${import_picocolors.default.dim("│")}
2321
- ${import_picocolors.default.dim("│")} Verdict: ${verdictZone}
2322
- ${import_picocolors.default.dim("│")} ${verdictText.split(`
2294
+ ${import_picocolors.default.dim("│")} ${verdictZone} ${verdictText.split(`
2323
2295
  `).join(`
2324
- ` + import_picocolors.default.dim("│") + " ")}
2296
+ ` + import_picocolors.default.dim("│") + " ")}
2325
2297
  ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2326
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgMagenta(" [ FINANCIAL & COMPUTE TOLL ] "))}
2327
- ${import_picocolors.default.dim("│")} Tokens Burnt ................. ${totalTokensStr} vs Human Judgment
2328
- ${import_picocolors.default.dim("│")} Cache Bloat ................. ${cacheBar} ${cachePct}% (Unmodified context)
2329
- ${import_picocolors.default.dim("│")} Regional Grid ................. ${regionStr}
2298
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgMagenta(" WHAT IT COST "))}
2299
+ ${import_picocolors.default.dim("│")} Tokens used ${import_picocolors.default.bold(totalTokensStr)}
2300
+ ${import_picocolors.default.dim("│")} Est. spend ${import_picocolors.default.bold(estUsdStr)}
2301
+ ${import_picocolors.default.dim("│")} Re-used context ${cacheBar} ${import_picocolors.default.bold(cachePct + "%")}
2302
+ ${import_picocolors.default.dim("│")} Energy ${import_picocolors.default.bold(co2Str)} ${import_picocolors.default.dim(`(${regionStr} grid, rough)`)}
2330
2303
  ${import_picocolors.default.dim("│")}
2331
- ${import_picocolors.default.dim("│")} Verdict: ${cacheVerdict}
2332
- ${import_picocolors.default.dim("│")} ${cacheText.split(`
2304
+ ${import_picocolors.default.dim("│")} ${cacheVerdict} ${cacheText.split(`
2333
2305
  `).join(`
2334
- ` + import_picocolors.default.dim("│") + " ")}
2306
+ ` + import_picocolors.default.dim("│") + " ")}
2335
2307
  ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2336
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgYellow(import_picocolors.default.black(" [ POLICY ENFORCEMENT ] ")))}
2337
- ${import_picocolors.default.dim("│")} Status .................................. ${policyStatus}
2338
- ${import_picocolors.default.dim("│")} Action .................................. ${policyAction}
2308
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgYellow(import_picocolors.default.black(" YOUR LIMIT ")))}
2309
+ ${import_picocolors.default.dim("│")} AI cap ${import_picocolors.default.bold("70%")} ${import_picocolors.default.dim("· change with: outlier policy")}
2310
+ ${import_picocolors.default.dim("│")} Status ${policyStatus} ${import_picocolors.default.dim("·")} ${policyAction}
2339
2311
  ${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
2340
- ${import_picocolors.default.dim("│")}
2341
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.italic(import_picocolors.default.dim("patterns emerge in the commit history,"))}
2342
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.italic(import_picocolors.default.dim("code becomes commoditized by algorithms."))}
2343
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.italic(import_picocolors.default.dim("human mastery is the only true moat."))}
2344
- ${import_picocolors.default.dim("│")}
2345
- ${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.cyan("***STAY VIGILANT***"))}
2312
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.dim(import_picocolors.default.italic("Run this before you start. Keep the skill while you"))}
2313
+ ${import_picocolors.default.dim("│")} ${import_picocolors.default.dim(import_picocolors.default.italic("use the speed."))}
2346
2314
  ${import_picocolors.default.dim("└────────────────────────────────────────────────────────")}`;
2347
2315
  } else {
2348
2316
  note(`status: ${authPct} AI Reliance | ${cachePct}% Cache Bloat | ${co2Str}`, `${import_picocolors.default.bold("[outlier]")} CI/CD Audit`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rosh100yx/outlier",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
4
4
  "description": "AI Code Governance & Capability Auditing for the Terminal. Measures AI reliance, context waste, and enforces local CI/CD policies.",
5
5
  "bin": {
6
6
  "outlier": "bin/outlier.js"
package/src/carbon.ts CHANGED
@@ -13,10 +13,12 @@ export interface CarbonStats {
13
13
  localCo2Kg: number;
14
14
  localRegion: string;
15
15
  sessions: number;
16
+ estUsd: number; // estimated spend in USD
17
+ costIsReal: boolean; // true if summed from the log's own cost field, false if estimated from tokens
16
18
  }
17
19
 
18
20
  export interface TokenLogParser {
19
- parse(): Promise<{ total: number, output: number, cache: number, sessions: number }>;
21
+ parse(): Promise<{ total: number, output: number, cache: number, sessions: number, cost: number }>;
20
22
  }
21
23
 
22
24
  export class ClaudeLogParser implements TokenLogParser {
@@ -30,13 +32,13 @@ export class ClaudeLogParser implements TokenLogParser {
30
32
  try {
31
33
  await access(logPath);
32
34
  } catch {
33
- return { total: 0, output: 0, cache: 0, sessions: 0 };
35
+ return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0 };
34
36
  }
35
37
 
36
38
  const text = await readFile(logPath, 'utf-8');
37
39
  const lines = text.trim().split('\n').filter(l => l.length > 0);
38
-
39
- let total = 0, output = 0, cache = 0;
40
+
41
+ let total = 0, output = 0, cache = 0, cost = 0;
40
42
  const sessions = new Set<string>();
41
43
 
42
44
  for (const line of lines) {
@@ -45,19 +47,27 @@ export class ClaudeLogParser implements TokenLogParser {
45
47
  total += data.total_tokens || 0;
46
48
  output += data.output_tokens || 0;
47
49
  cache += data.cache_read || 0;
50
+ cost += data.cost_usd || 0; // present when the log was written with a cost field
48
51
  if (data.session_id) sessions.add(data.session_id);
49
52
  } catch (e) {}
50
53
  }
51
- return { total, output, cache, sessions: sessions.size };
54
+ return { total, output, cache, sessions: sessions.size, cost };
52
55
  }
53
56
  }
54
57
 
55
58
  class CursorLogParser implements TokenLogParser {
56
59
  async parse() {
57
- return { total: 0, output: 0, cache: 0, sessions: 0 };
60
+ return { total: 0, output: 0, cache: 0, sessions: 0, cost: 0 };
58
61
  }
59
62
  }
60
63
 
64
+ // Rough blended token pricing (USD per 1M tokens) for when the log has no cost field.
65
+ // Conservative mid-points across current models; labeled "rough" in the UI.
66
+ function estimateUsd(output: number, cacheRead: number, total: number): number {
67
+ const otherInput = Math.max(0, total - output - cacheRead);
68
+ return (output / 1e6) * 9 + (cacheRead / 1e6) * 0.3 + (otherInput / 1e6) * 3;
69
+ }
70
+
61
71
  function getLocalGridFactor(): { region: string, factor: number } {
62
72
  try {
63
73
  const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -73,7 +83,7 @@ function getLocalGridFactor(): { region: string, factor: number } {
73
83
  export async function getCarbonStats(): Promise<CarbonStats> {
74
84
  const parsers: TokenLogParser[] = [new ClaudeLogParser(), new CursorLogParser()];
75
85
 
76
- let totalTokens = 0, outputTokens = 0, cacheReadTokens = 0, sessions = 0;
86
+ let totalTokens = 0, outputTokens = 0, cacheReadTokens = 0, sessions = 0, loggedCost = 0;
77
87
 
78
88
  for (const parser of parsers) {
79
89
  const stats = await parser.parse();
@@ -81,11 +91,16 @@ export async function getCarbonStats(): Promise<CarbonStats> {
81
91
  outputTokens += stats.output;
82
92
  cacheReadTokens += stats.cache;
83
93
  sessions += stats.sessions;
94
+ loggedCost += stats.cost;
84
95
  }
85
96
 
86
97
  const energyKwh = (outputTokens / 1_000_000) * 0.662;
87
98
  const localGrid = getLocalGridFactor();
88
99
 
100
+ // Prefer the log's own cost field (accurate); fall back to a rough token estimate.
101
+ const costIsReal = loggedCost > 0;
102
+ const estUsd = costIsReal ? loggedCost : estimateUsd(outputTokens, cacheReadTokens, totalTokens);
103
+
89
104
  return {
90
105
  totalTokens,
91
106
  outputTokens,
@@ -95,6 +110,8 @@ export async function getCarbonStats(): Promise<CarbonStats> {
95
110
  co2KgFrance: (energyKwh * gridFactors.france) / 1000,
96
111
  localCo2Kg: (energyKwh * localGrid.factor) / 1000,
97
112
  localRegion: localGrid.region,
98
- sessions
113
+ sessions,
114
+ estUsd,
115
+ costIsReal
99
116
  };
100
117
  }
package/src/cli.ts CHANGED
@@ -21,7 +21,6 @@ const ASCII_LOGO = `
21
21
  let finalReceipt = '';
22
22
 
23
23
  async function runOnboarding() {
24
- console.clear();
25
24
  console.log(pc.cyan(ASCII_LOGO));
26
25
  intro(pc.inverse(' outlier: Welcome '));
27
26
 
@@ -79,7 +78,6 @@ async function main() {
79
78
  action = 'status';
80
79
  }
81
80
 
82
- console.clear();
83
81
  console.log(pc.cyan(ASCII_LOGO));
84
82
  const pkg = require('../package.json');
85
83
  console.log(pc.dim(` Outlier v${pkg.version} · AI Code Reliance & Telemetry Engine\n`));
@@ -278,29 +276,12 @@ Conservative Floor: ${color(nmPct + '%')}`,
278
276
  try {
279
277
  let authPct = '0%';
280
278
  let ruleFailures = 0;
281
- let authWarning = '';
282
- let wittyRemark = isStrict ? '' : 'No git history (・_・ヾ';
283
- let mentorString = '';
284
-
279
+
285
280
  if (gitStats) {
286
281
  authPct = `${(gitStats.ratio * 100).toFixed(1)}%`;
287
-
288
- if (!isStrict) {
289
- if (gitStats.ratio < 0.1) wittyRemark = 'Artisan, hand-crafted code. Very 2019 of you (=^ ◡ ^=)';
290
- else if (gitStats.ratio < 0.6) wittyRemark = 'A true centaur. Half human, half matrix (=`ω´=)';
291
- else if (gitStats.ratio < 0.95) wittyRemark = 'Orchestrating the swarm. You are the manager now (ФДФ)';
292
- else wittyRemark = '100% Cybernetic. Codebase goes brrrrr (=ಠᆽಠ=)';
293
- }
294
-
295
- if (gitStats.ratio > 0.7) {
296
- authWarning = pc.red(isStrict ? `⚠ High Risk Surface: ${authPct} AI-generated. Human review required.` : `⚠ Mentoring Emergency: ${authPct} AI-generated. High risk of skill atrophy.`);
297
- if (!isStrict) {
298
- mentorString = `\n mentor: ${pc.blue('💡 Architecture Challenge Pending (See Git Hook)')}`;
299
- }
300
- ruleFailures++;
301
- }
282
+ if (gitStats.ratio > 0.7) ruleFailures++;
302
283
  }
303
-
284
+
304
285
  let cachePct = '0';
305
286
  let co2Str = '0.0kg';
306
287
  let regionStr = 'Global Average';
@@ -312,44 +293,35 @@ Conservative Floor: ${color(nmPct + '%')}`,
312
293
  regionStr = carbon.localRegion;
313
294
  }
314
295
 
315
- const vibeRow = !isStrict ? `\n vibe: ${pc.italic(wittyRemark)}` : '';
316
- const capIcon = isStrict ? '' : '(Ф∇Ф) ';
317
- const authIcon = isStrict ? '' : '(=^・ω・^=) ';
318
- const costIcon = isStrict ? '' : '(O_O;) ';
319
- const failIcon = isStrict ? '⚠' : '(=ಠᆽಠ=)';
320
- const passIcon = isStrict ? '✓' : '(=^ ◡ ^=)';
321
-
322
- note(
323
- `${capIcon}${pc.dim('[1] Capability Engine')} ${pc.cyan('▰▰▰▰▰▰▱▱▱▱')} ${pc.bold('Active')}
324
- status: ${pc.green('✓ Configured')}
325
- ${authIcon}${pc.dim('[2] AI Code Reliance')} ${pc.yellow('▰▰▰▰▰▰▰▰▱▱')} ${pc.bold(`${authPct} Reliance`)}${vibeRow}
326
- gate: ${gitStats && gitStats.ratio <= 0.7 ? pc.green('✓ Human Mastery Sustained') : `${pc.red(`${failIcon} Deskilling Risk Detected`)} ${pc.red('⚠ Security Audit Required')}`}${mentorString}
327
- ${costIcon}${pc.dim('[3] Tokenomics & Cost')} ${pc.magenta('▰▰▰▰▰▰▰▰▰▱')} ${pc.bold(`${cachePct}% Cache Bloat`)}
328
- waste: ${pc.yellow(`⚠ ${cachePct}% of tokens are redundant context reads`)}
329
- carbon: ${pc.green(`✓ ${co2Str} (Est. ${regionStr} Grid)`)}
330
- ${pc.bold('Governance:')} ${ruleFailures > 0 ? pc.red(`${failIcon} ${ruleFailures + 1} policy failures`) : pc.green(`${passIcon} All clear`)}`,
331
- `${pc.bold('[outlier]')} ${5 - (ruleFailures+1)}/5 policies • ${authWarning || pc.green(`${passIcon} safe surface`)} • ${co2Str}`
332
- );
333
-
334
- const timestamp = new Date().toISOString().split('T')[0];
296
+ // The thermal receipt below is the single canonical output for `status`.
297
+ // (The old @clack dashboard panel was removed: it duplicated the receipt's
298
+ // numbers in a second format, doubling the output on every run.)
335
299
  const isDanger = gitStats && gitStats.ratio > 0.7;
336
- const verdictZone = isDanger ? pc.red('DANGER ZONE') : pc.green('SAFE / SOVEREIGN');
337
- const verdictText = isDanger
338
- ? `You are transitioning from 'Creator' to 'Reviewer'.\n At this trajectory, you risk losing architectural \n muscle memory on this codebase within 6 months.`
339
- : `You are maintaining strong architectural intimacy.\n Your human judgement remains the primary driver\n of logic in this system.`;
340
-
300
+ const verdictZone = isDanger ? pc.red('Mostly AI') : pc.green('You\'re driving');
301
+ const verdictText = isDanger
302
+ ? `AI wrote most of this. Read it through so you can\n still debug it yourself when the agent isn't around.`
303
+ : `You're still writing the core of this. Good —\n that's how you keep the skill.`;
304
+
341
305
  const isInefficient = parseFloat(cachePct) > 40;
342
- const cacheVerdict = isInefficient ? pc.yellow('INEFFICIENT') : pc.green('EFFICIENT');
343
- const cacheText = isInefficient
344
- ? `You are burning paid API tokens and excess compute\n on files the agent isn't even touching.`
345
- : `Your token usage and human judgment are tightly\n coupled. High signal-to-noise ratio.`;
346
-
347
- const policyStatus = ruleFailures > 0 ? pc.red('BLOCKED 🛑 (Threshold Exceeded)') : pc.green('PASS ✅ (Within Threshold)');
348
- const policyAction = ruleFailures > 0 ? 'Triggering Mandatory Mentoring Scenario.' : 'No intervention required.';
349
-
350
- const totalTokensStr = carbon ? (carbon.totalTokens / 1000).toFixed(1) + 'k' : '0';
351
- const humanSov = gitStats ? ((1 - gitStats.ratio) * 100).toFixed(1) + '%' : '100%';
352
- const authorshipStr = authPct + (isDanger ? pc.red(' (High Reliance)') : pc.green(' (Healthy)'));
306
+ const cacheVerdict = isInefficient ? pc.yellow('Lots of re-reads') : pc.green('Lean');
307
+ const cacheText = isInefficient
308
+ ? `Most of your tokens just re-send old context.\n It's normal for agents, but it's most of the bill.`
309
+ : `Little wasted context. Your spend is mostly\n real work.`;
310
+
311
+ const policyStatus = ruleFailures > 0 ? pc.red('Over your limit') : pc.green('Within limit');
312
+ const policyAction = ruleFailures > 0 ? 'Heads up only — nothing was blocked.' : 'Nothing to do.';
313
+
314
+ const fmtTokens = (n: number) =>
315
+ n >= 1_000_000_000 ? (n / 1_000_000_000).toFixed(1) + 'B'
316
+ : n >= 1_000_000 ? (n / 1_000_000).toFixed(1) + 'M'
317
+ : n >= 1_000 ? (n / 1_000).toFixed(1) + 'k'
318
+ : String(n);
319
+ const totalTokensStr = carbon ? fmtTokens(carbon.totalTokens) : '0';
320
+ const estUsdStr = carbon
321
+ ? '$' + carbon.estUsd.toFixed(2) + (carbon.costIsReal ? '' : pc.dim(' (rough)'))
322
+ : pc.dim('n/a');
323
+ const humanSov = gitStats ? ((1 - gitStats.ratio) * 100).toFixed(0) + '%' : '100%';
324
+ const authorshipStr = pc.bold(authPct) + (isDanger ? pc.red(' AI-written') : pc.green(' AI-written'));
353
325
 
354
326
  const getProgressBar = (pct: number, length = 10) => {
355
327
  const filled = Math.max(0, Math.min(length, Math.round((pct / 100) * length)));
@@ -368,34 +340,29 @@ ${pc.bold('Governance:')} ${ruleFailures > 0 ? pc.red(`${failIcon} ${ruleFailure
368
340
 
369
341
  finalReceipt = `
370
342
  ${pc.dim('┌────────────────────────────────────────────────────────')}
371
- ${pc.dim('│')} ${pc.cyan('█▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█')} ${pc.bold(':: THERMAL AUDIT RECEIPT')}
372
- ${pc.dim('│')} ${pc.cyan('█▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄')} ${pc.dim(`:: TIMESTAMP: ${dateStr}`)}
343
+ ${pc.dim('│')} ${pc.cyan('█▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█')} ${pc.bold(':: CODE AUDIT')}
344
+ ${pc.dim('│')} ${pc.cyan('█▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄')} ${pc.dim(`:: ${repoName} · ${dateStr}`)}
373
345
  ${pc.dim('├────────────────────────────────────────────────────────')}
374
- ${pc.dim('│')} ${pc.bold(pc.bgBlue(' [ COGNITIVE BUDGET ] '))}
375
- ${pc.dim('│')} AI Authorship ................. ${aiBar} ${authorshipStr}
376
- ${pc.dim('│')} Human Sovereignty ................. ${humanBar} ${humanSov}
346
+ ${pc.dim('│')} ${pc.bold(pc.bgBlue(' WHO WROTE THE CODE '))}
347
+ ${pc.dim('│')} AI ${aiBar} ${authorshipStr}
348
+ ${pc.dim('│')} You ${humanBar} ${pc.bold(humanSov)}
377
349
  ${pc.dim('│')}
378
- ${pc.dim('│')} Verdict: ${verdictZone}
379
- ${pc.dim('│')} ${verdictText.split('\n').join('\n ' + pc.dim('│') + ' ')}
350
+ ${pc.dim('│')} ${verdictZone} ${verdictText.split('\n').join('\n ' + pc.dim('│') + ' ')}
380
351
  ${pc.dim('├────────────────────────────────────────────────────────')}
381
- ${pc.dim('│')} ${pc.bold(pc.bgMagenta(' [ FINANCIAL & COMPUTE TOLL ] '))}
382
- ${pc.dim('│')} Tokens Burnt ................. ${totalTokensStr} vs Human Judgment
383
- ${pc.dim('│')} Cache Bloat ................. ${cacheBar} ${cachePct}% (Unmodified context)
384
- ${pc.dim('│')} Regional Grid ................. ${regionStr}
352
+ ${pc.dim('│')} ${pc.bold(pc.bgMagenta(' WHAT IT COST '))}
353
+ ${pc.dim('│')} Tokens used ${pc.bold(totalTokensStr)}
354
+ ${pc.dim('│')} Est. spend ${pc.bold(estUsdStr)}
355
+ ${pc.dim('│')} Re-used context ${cacheBar} ${pc.bold(cachePct + '%')}
356
+ ${pc.dim('│')} Energy ${pc.bold(co2Str)} ${pc.dim(`(${regionStr} grid, rough)`)}
385
357
  ${pc.dim('│')}
386
- ${pc.dim('│')} Verdict: ${cacheVerdict}
387
- ${pc.dim('│')} ${cacheText.split('\n').join('\n ' + pc.dim('│') + ' ')}
358
+ ${pc.dim('│')} ${cacheVerdict} ${cacheText.split('\n').join('\n ' + pc.dim('│') + ' ')}
388
359
  ${pc.dim('├────────────────────────────────────────────────────────')}
389
- ${pc.dim('│')} ${pc.bold(pc.bgYellow(pc.black(' [ POLICY ENFORCEMENT ] ')))}
390
- ${pc.dim('│')} Status .................................. ${policyStatus}
391
- ${pc.dim('│')} Action .................................. ${policyAction}
360
+ ${pc.dim('│')} ${pc.bold(pc.bgYellow(pc.black(' YOUR LIMIT ')))}
361
+ ${pc.dim('│')} AI cap ${pc.bold('70%')} ${pc.dim('· change with: outlier policy')}
362
+ ${pc.dim('│')} Status ${policyStatus} ${pc.dim('·')} ${policyAction}
392
363
  ${pc.dim('├────────────────────────────────────────────────────────')}
393
- ${pc.dim('│')}
394
- ${pc.dim('│')} ${pc.italic(pc.dim('patterns emerge in the commit history,'))}
395
- ${pc.dim('│')} ${pc.italic(pc.dim('code becomes commoditized by algorithms.'))}
396
- ${pc.dim('│')} ${pc.italic(pc.dim('human mastery is the only true moat.'))}
397
- ${pc.dim('│')}
398
- ${pc.dim('│')} ${pc.bold(pc.cyan('***STAY VIGILANT***'))}
364
+ ${pc.dim('│')} ${pc.dim(pc.italic('Run this before you start. Keep the skill while you'))}
365
+ ${pc.dim('│')} ${pc.dim(pc.italic('use the speed.'))}
399
366
  ${pc.dim('└────────────────────────────────────────────────────────')}`;
400
367
  } else {
401
368
  note(