@rosh100yx/outlier 0.7.0 → 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/README.md +70 -54
- package/bin/outlier.js +388 -36
- package/package.json +1 -1
- package/src/aggregate.ts +59 -0
- package/src/capabilities.ts +5 -0
- package/src/carbon.ts +33 -4
- package/src/cli.ts +164 -12
- package/src/economics.ts +66 -0
- package/src/emissions.ts +7 -3
- package/src/insights.ts +109 -0
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.
|
|
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"
|
|
@@ -2053,6 +2108,33 @@ function estimateUsd(output, cacheRead, total) {
|
|
|
2053
2108
|
const otherInput = Math.max(0, total - output - cacheRead);
|
|
2054
2109
|
return output / 1e6 * 9 + cacheRead / 1e6 * 0.3 + otherInput / 1e6 * 3;
|
|
2055
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
|
+
}
|
|
2056
2138
|
function getLocalGridFactor() {
|
|
2057
2139
|
try {
|
|
2058
2140
|
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
@@ -2084,8 +2166,10 @@ async function getCarbonStats() {
|
|
|
2084
2166
|
outputByModel[m2] = (outputByModel[m2] || 0) + out;
|
|
2085
2167
|
}
|
|
2086
2168
|
}
|
|
2087
|
-
const energyKwh = energyKwhByModel(outputByModel);
|
|
2088
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;
|
|
2089
2173
|
const sources = detectSources();
|
|
2090
2174
|
const costIsReal = loggedCost > 0;
|
|
2091
2175
|
const estUsd = costIsReal ? loggedCost : estimateUsd(outputTokens, cacheReadTokens, totalTokens);
|
|
@@ -2096,8 +2180,8 @@ async function getCarbonStats() {
|
|
|
2096
2180
|
energyKwh,
|
|
2097
2181
|
co2KgVietnam: energyKwh * grid_factors_default.vietnam / 1000,
|
|
2098
2182
|
co2KgFrance: energyKwh * grid_factors_default.france / 1000,
|
|
2099
|
-
localCo2Kg: energyKwh * localGrid.factor / 1000,
|
|
2100
|
-
localRegion: localGrid.region,
|
|
2183
|
+
localCo2Kg: measuredCo2 !== null ? measuredCo2 : energyKwh * localGrid.factor / 1000,
|
|
2184
|
+
localRegion: measured ? "CodeCarbon (measured)" : localGrid.region,
|
|
2101
2185
|
sessions,
|
|
2102
2186
|
estUsd,
|
|
2103
2187
|
costIsReal,
|
|
@@ -2189,7 +2273,11 @@ async function getCapabilitiesStats(repoPath = process.cwd(), homeDirPath = home
|
|
|
2189
2273
|
for (const cfg of [
|
|
2190
2274
|
join3(homeDirPath, ".claude.json"),
|
|
2191
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"),
|
|
2192
2279
|
join3(repoPath, ".mcp.json"),
|
|
2280
|
+
join3(repoPath, ".cursor", "mcp.json"),
|
|
2193
2281
|
join3(repoPath, ".claude", "settings.json")
|
|
2194
2282
|
]) {
|
|
2195
2283
|
const j = readJson(cfg);
|
|
@@ -2229,23 +2317,134 @@ async function getCapabilitiesStats(repoPath = process.cwd(), homeDirPath = home
|
|
|
2229
2317
|
return { mcps, skills, subagents, hooks, hasOrchestration, blastRadius: radius, blastReasons: reasons };
|
|
2230
2318
|
}
|
|
2231
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]);
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2232
2387
|
// src/cli.ts
|
|
2233
|
-
|
|
2234
|
-
|
|
2388
|
+
init_economics();
|
|
2389
|
+
|
|
2390
|
+
// src/aggregate.ts
|
|
2391
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
|
|
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";
|
|
2235
2434
|
|
|
2236
2435
|
// src/agent.ts
|
|
2237
2436
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
2238
|
-
import { readFileSync as
|
|
2239
|
-
import { join as
|
|
2437
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
2438
|
+
import { join as join5 } from "path";
|
|
2240
2439
|
import os from "os";
|
|
2241
2440
|
function detectAgent() {
|
|
2242
2441
|
const agents = ["claude", "cursor", "aider", "hermes", "cody", "continue", "opencode", "gemini"];
|
|
2243
2442
|
try {
|
|
2244
2443
|
const home = os.homedir();
|
|
2245
|
-
const historyFiles = [
|
|
2444
|
+
const historyFiles = [join5(home, ".zsh_history"), join5(home, ".bash_history")];
|
|
2246
2445
|
for (const file of historyFiles) {
|
|
2247
2446
|
if (existsSync3(file)) {
|
|
2248
|
-
const content =
|
|
2447
|
+
const content = readFileSync3(file, "utf8");
|
|
2249
2448
|
const lines = content.split(`
|
|
2250
2449
|
`).filter(Boolean).slice(-500).reverse();
|
|
2251
2450
|
for (const line of lines) {
|
|
@@ -2282,6 +2481,54 @@ var ASCII_LOGO = `
|
|
|
2282
2481
|
\\____/|_| |_| |_| |_| |_|___|_____|_| \\_\\
|
|
2283
2482
|
`;
|
|
2284
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
|
+
}
|
|
2285
2532
|
async function emitJson() {
|
|
2286
2533
|
const pkg = require_package();
|
|
2287
2534
|
const [gitStats, carbon, caps] = await Promise.all([
|
|
@@ -2337,7 +2584,9 @@ async function emitJson() {
|
|
|
2337
2584
|
policy: {
|
|
2338
2585
|
aiCapPercent: cap * 100,
|
|
2339
2586
|
status: aiRatio > cap ? "over" : "within"
|
|
2340
|
-
}
|
|
2587
|
+
},
|
|
2588
|
+
insights: deriveInsights({ authorship: gitStats, carbon, caps, policyCap: cap }),
|
|
2589
|
+
economics: projectEconomics({ aiRatio, estUsdSession: carbon ? carbon.estUsd : 0, teamSize: 1 })
|
|
2341
2590
|
};
|
|
2342
2591
|
process.stdout.write(JSON.stringify(out, null, 2) + `
|
|
2343
2592
|
`);
|
|
@@ -2363,18 +2612,18 @@ As agents write more of our code, we lose visibility into:
|
|
|
2363
2612
|
cancel("Onboarding paused. Run outlier again when you are ready.");
|
|
2364
2613
|
process.exit(0);
|
|
2365
2614
|
}
|
|
2366
|
-
const configPath =
|
|
2615
|
+
const configPath = join6(os2.homedir(), ".outlier_config");
|
|
2367
2616
|
writeFileSync(configPath, JSON.stringify({ onboarded: true, date: new Date().toISOString() }));
|
|
2368
2617
|
}
|
|
2369
2618
|
async function main() {
|
|
2370
2619
|
let action = process.argv[2];
|
|
2371
2620
|
if (action === "daily-greeting") {
|
|
2372
|
-
const configPath2 =
|
|
2621
|
+
const configPath2 = join6(os2.homedir(), ".outlier_config");
|
|
2373
2622
|
const today = new Date().toISOString().split("T")[0];
|
|
2374
2623
|
let alreadyRun = false;
|
|
2375
2624
|
if (existsSync4(configPath2)) {
|
|
2376
2625
|
try {
|
|
2377
|
-
const cfg = JSON.parse(
|
|
2626
|
+
const cfg = JSON.parse(readFileSync4(configPath2, "utf8"));
|
|
2378
2627
|
if (cfg.lastGreetingDate === today) {
|
|
2379
2628
|
alreadyRun = true;
|
|
2380
2629
|
} else {
|
|
@@ -2385,7 +2634,13 @@ async function main() {
|
|
|
2385
2634
|
}
|
|
2386
2635
|
if (alreadyRun)
|
|
2387
2636
|
process.exit(0);
|
|
2388
|
-
|
|
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);
|
|
2389
2644
|
}
|
|
2390
2645
|
if (process.argv.includes("--json")) {
|
|
2391
2646
|
await emitJson();
|
|
@@ -2403,6 +2658,7 @@ WHAT OUTLIER DOES`));
|
|
|
2403
2658
|
`));
|
|
2404
2659
|
console.log(import_picocolors.default.bold("COMMANDS:"));
|
|
2405
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)`);
|
|
2406
2662
|
console.log(` ${import_picocolors.default.cyan("outlier status")} Full audit: who wrote the code, what it cost, your limit`);
|
|
2407
2663
|
console.log(` ${import_picocolors.default.cyan("outlier status --save")} Save the audit to ./outlier-audit.txt`);
|
|
2408
2664
|
console.log(` ${import_picocolors.default.cyan("outlier --json")} Machine-readable audit (for agents, CI, swarms)`);
|
|
@@ -2420,7 +2676,7 @@ WHAT OUTLIER DOES`));
|
|
|
2420
2676
|
console.log(import_picocolors.default.dim("How it works → https://github.com/rosh100yx/outlier#how-it-works"));
|
|
2421
2677
|
process.exit(0);
|
|
2422
2678
|
}
|
|
2423
|
-
const configPath =
|
|
2679
|
+
const configPath = join6(os2.homedir(), ".outlier_config");
|
|
2424
2680
|
if (!existsSync4(configPath) && !action) {
|
|
2425
2681
|
await runOnboarding();
|
|
2426
2682
|
action = "status";
|
|
@@ -2432,7 +2688,7 @@ WHAT OUTLIER DOES`));
|
|
|
2432
2688
|
if (action === "init" || action === "uninit") {
|
|
2433
2689
|
const shell = process.env.SHELL || "";
|
|
2434
2690
|
const rcName = shell.includes("zsh") ? ".zshrc" : ".bashrc";
|
|
2435
|
-
const rcPath =
|
|
2691
|
+
const rcPath = join6(os2.homedir(), rcName);
|
|
2436
2692
|
const START_MARKER = "# --- OUTLIER PRE-FLIGHT RITUAL START ---";
|
|
2437
2693
|
const END_MARKER = "# --- OUTLIER PRE-FLIGHT RITUAL END ---";
|
|
2438
2694
|
const BLOCK = `
|
|
@@ -2453,7 +2709,7 @@ ${END_MARKER}
|
|
|
2453
2709
|
}
|
|
2454
2710
|
let content = "";
|
|
2455
2711
|
if (existsSync4(rcPath))
|
|
2456
|
-
content =
|
|
2712
|
+
content = readFileSync4(rcPath, "utf8");
|
|
2457
2713
|
if (content.includes(START_MARKER)) {
|
|
2458
2714
|
note(`Outlier is already initialized in ${rcName}`);
|
|
2459
2715
|
} else {
|
|
@@ -2463,7 +2719,7 @@ ${END_MARKER}
|
|
|
2463
2719
|
process.exit(0);
|
|
2464
2720
|
} else if (action === "uninit") {
|
|
2465
2721
|
if (existsSync4(rcPath)) {
|
|
2466
|
-
let content =
|
|
2722
|
+
let content = readFileSync4(rcPath, "utf8");
|
|
2467
2723
|
if (content.includes(START_MARKER)) {
|
|
2468
2724
|
const regex = new RegExp(`\\n?${START_MARKER}[\\s\\S]*?${END_MARKER}\\n?`, "g");
|
|
2469
2725
|
content = content.replace(regex, `
|
|
@@ -2532,10 +2788,10 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
|
|
|
2532
2788
|
let carbon = null;
|
|
2533
2789
|
let capabilities = null;
|
|
2534
2790
|
let skipDelay = false;
|
|
2535
|
-
const configPath2 =
|
|
2791
|
+
const configPath2 = join6(os2.homedir(), ".outlier_config");
|
|
2536
2792
|
if (existsSync4(configPath2)) {
|
|
2537
2793
|
try {
|
|
2538
|
-
const cfg = JSON.parse(
|
|
2794
|
+
const cfg = JSON.parse(readFileSync4(configPath2, "utf8"));
|
|
2539
2795
|
if (cfg.seenNarration)
|
|
2540
2796
|
skipDelay = true;
|
|
2541
2797
|
} catch (e) {}
|
|
@@ -2573,7 +2829,7 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
|
|
|
2573
2829
|
await new Promise((r2) => setTimeout(r2, 600));
|
|
2574
2830
|
if (!skipDelay) {
|
|
2575
2831
|
try {
|
|
2576
|
-
const cfg = existsSync4(configPath2) ? JSON.parse(
|
|
2832
|
+
const cfg = existsSync4(configPath2) ? JSON.parse(readFileSync4(configPath2, "utf8")) : {};
|
|
2577
2833
|
cfg.seenNarration = true;
|
|
2578
2834
|
writeFileSync(configPath2, JSON.stringify(cfg));
|
|
2579
2835
|
} catch (e) {}
|
|
@@ -2619,6 +2875,14 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
|
|
|
2619
2875
|
const risky = capabilities.mcps.filter((m2) => ["money", "exec", "deploy", "write-remote", "write-local"].includes(m2.reach)).length;
|
|
2620
2876
|
reachStr = `${col(import_picocolors.default.bold(rc))} · ${capabilities.mcps.length} tools` + (risky ? import_picocolors.default.dim(`, ${risky} can write/deploy`) : "");
|
|
2621
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
|
+
`);
|
|
2622
2886
|
const isDanger = gitStats && gitStats.ratio > 0.7;
|
|
2623
2887
|
const verdictZone = isDanger ? import_picocolors.default.red("Mostly AI") : import_picocolors.default.green("You're driving");
|
|
2624
2888
|
const verdictText = isDanger ? `AI wrote most of this. Read it through so you can
|
|
@@ -2680,6 +2944,9 @@ Conservative Floor: ${color(nmPct + "%")}`, "Git Authorship Breakdown");
|
|
|
2680
2944
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.bgYellow(import_picocolors.default.black(" YOUR LIMIT ")))}
|
|
2681
2945
|
${import_picocolors.default.dim("│")} AI cap ${import_picocolors.default.bold("70%")} ${import_picocolors.default.dim("· change with: outlier policy")}
|
|
2682
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}
|
|
2683
2950
|
${import_picocolors.default.dim("├────────────────────────────────────────────────────────")}
|
|
2684
2951
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("Numbers are local estimates — authorship is a proxy and")}
|
|
2685
2952
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("carbon is rough. How it works: outlier --help")}
|
|
@@ -2733,6 +3000,53 @@ ${import_picocolors.default.dim("This is your attack surface. Fewer write/deploy
|
|
|
2733
3000
|
s.stop("Audit failed");
|
|
2734
3001
|
console.error(import_picocolors.default.red(e.message));
|
|
2735
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("");
|
|
2736
3050
|
} else if (action === "policy") {
|
|
2737
3051
|
const tier = await select({
|
|
2738
3052
|
message: "Select the governance tier to configure:",
|
|
@@ -2762,7 +3076,7 @@ ${import_picocolors.default.dim("This is your attack surface. Fewer write/deploy
|
|
|
2762
3076
|
process.exit(0);
|
|
2763
3077
|
}
|
|
2764
3078
|
s.start(`Applying ${tier} policy guardrails...`);
|
|
2765
|
-
const gitDir =
|
|
3079
|
+
const gitDir = join6(process.cwd(), ".git");
|
|
2766
3080
|
const isRepo = existsSync4(gitDir);
|
|
2767
3081
|
if (!isRepo) {
|
|
2768
3082
|
console.error(import_picocolors.default.red("Must be run inside a git repository"));
|
|
@@ -2771,7 +3085,7 @@ ${import_picocolors.default.dim("This is your attack surface. Fewer write/deploy
|
|
|
2771
3085
|
const isStrict = process.argv.includes("--strict");
|
|
2772
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%)."
|
|
2773
3087
|
echo "Take a moment to review your recent architectural decisions. Ensure you still understand the system."`;
|
|
2774
|
-
const hookPath =
|
|
3088
|
+
const hookPath = join6(gitDir, "hooks", "pre-commit");
|
|
2775
3089
|
if (existsSync4(hookPath)) {
|
|
2776
3090
|
const { copyFileSync } = __require("fs");
|
|
2777
3091
|
copyFileSync(hookPath, `${hookPath}.backup`);
|
|
@@ -2803,16 +3117,31 @@ Rule 1: ${import_picocolors.default.green(`AI Authorship must not exceed $
|
|
|
2803
3117
|
Rule 2: ${import_picocolors.default.green("Require human review on consecutive high-AI sprints")}
|
|
2804
3118
|
Enforcement: ${import_picocolors.default.cyan("Local pre-commit hook installed (backup created)")}`, "Active Governance Policy");
|
|
2805
3119
|
} else if (tier === "regulatory") {
|
|
2806
|
-
s.start("Generating
|
|
2807
|
-
await
|
|
2808
|
-
const
|
|
2809
|
-
|
|
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) + `
|
|
2810
3138
|
`);
|
|
2811
|
-
s.stop("Audit
|
|
2812
|
-
note(`Jurisdiction: ${import_picocolors.default.bold("Vietnam (Decree 142)")}
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
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");
|
|
2816
3145
|
}
|
|
2817
3146
|
} else if (action === "participate") {
|
|
2818
3147
|
s.start("Connecting to the Outlier research project...");
|
|
@@ -2884,6 +3213,28 @@ ${import_picocolors.default.bold("Submit here (and drop your screenshot!):")} ${
|
|
|
2884
3213
|
■ Next 5-10 Years (The 1M+ LOC Crisis)`));
|
|
2885
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.
|
|
2886
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
|
+
}
|
|
2887
3238
|
} else if (action === "knowledge") {
|
|
2888
3239
|
console.log(`
|
|
2889
3240
|
` + import_picocolors.default.bold(import_picocolors.default.bgBlue(" CORE LITERATURE & REFERENCES ")) + `
|
|
@@ -2897,12 +3248,13 @@ Read the full academic foundation at: ${import_picocolors.default.underline("htt
|
|
|
2897
3248
|
}
|
|
2898
3249
|
outro("Done — nothing left your machine. (How it works: outlier --help)");
|
|
2899
3250
|
if (typeof finalReceipt !== "undefined" && finalReceipt) {
|
|
2900
|
-
|
|
3251
|
+
const boxed = closeBox(finalReceipt);
|
|
3252
|
+
console.log(boxed);
|
|
2901
3253
|
if (process.argv.includes("--save")) {
|
|
2902
3254
|
const stripAnsi = (s2) => s2.replace(/\x1b\[[0-9;]*m/g, "");
|
|
2903
|
-
const savePath =
|
|
3255
|
+
const savePath = join6(process.cwd(), "outlier-audit.txt");
|
|
2904
3256
|
try {
|
|
2905
|
-
writeFileSync(savePath, stripAnsi(
|
|
3257
|
+
writeFileSync(savePath, stripAnsi(boxed).trimStart() + `
|
|
2906
3258
|
`);
|
|
2907
3259
|
console.log(import_picocolors.default.dim(`
|
|
2908
3260
|
\uD83D\uDCBE Saved to ${savePath}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rosh100yx/outlier",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.2",
|
|
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"
|