@rosh100yx/outlier 0.4.10 → 0.4.15
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 +40 -7
- package/bin/outlier.js +64 -149
- package/bin/postinstall.js +6 -3
- package/package.json +2 -2
- package/src/cli.ts +20 -81
package/README.md
CHANGED
|
@@ -18,8 +18,26 @@
|
|
|
18
18
|
</p>
|
|
19
19
|
|
|
20
20
|
<br/>
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
┌────────────────────────────────────────────────────────┐
|
|
24
|
+
│ █▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█ :: THERMAL AUDIT RECEIPT │
|
|
25
|
+
│ █▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄ :: TIMESTAMP: 2026-06-23 │
|
|
26
|
+
├────────────────────────────────────────────────────────┤
|
|
27
|
+
│ [ COGNITIVE BUDGET ] │
|
|
28
|
+
│ AI Authorship ................. ▇▇▇▇░░░░░░ 40% │
|
|
29
|
+
│ Human Sovereignty ................. ▇▇▇▇▇▇░░░░ 60% │
|
|
30
|
+
│ │
|
|
31
|
+
│ ↳ Verdict: (=^ ◡ ^=) CENTAUR │
|
|
32
|
+
│ Healthy symbiosis. You orchestrate agents │
|
|
33
|
+
│ but maintain architectural authority. │
|
|
34
|
+
├────────────────────────────────────────────────────────┤
|
|
35
|
+
│ [ FINANCIAL & COMPUTE TOLL ] │
|
|
36
|
+
│ Tokens Burnt ................. 3.12M vs Human │
|
|
37
|
+
│ Cache Bloat ................. ▇▇▇▇▇▇▇▇░░ 80% │
|
|
38
|
+
│ Regional Grid ................. 1.54 kgCO2 │
|
|
39
|
+
└────────────────────────────────────────────────────────┘
|
|
40
|
+
```
|
|
23
41
|
</div>
|
|
24
42
|
|
|
25
43
|
## How It Works
|
|
@@ -50,13 +68,28 @@
|
|
|
50
68
|
## Commands
|
|
51
69
|
| Command | Purpose |
|
|
52
70
|
|---------|---------|
|
|
53
|
-
| `outlier` | Start the interactive
|
|
54
|
-
| `outlier
|
|
55
|
-
| `outlier
|
|
56
|
-
| `outlier authorship` | Scan git history for AI co-authorship ratio and Hallucination Risk |
|
|
71
|
+
| `outlier` | Start the interactive Interactive Menu |
|
|
72
|
+
| `outlier status` | Run the full AI reliance & capability audit |
|
|
73
|
+
| `outlier authorship` | Scan git history for AI co-authorship ratio |
|
|
57
74
|
| `outlier carbon` | Scan local logs for context waste & token costs |
|
|
75
|
+
| `outlier capabilities` | Audit active MCPs, skills, and orchestrations |
|
|
58
76
|
| `outlier policy` | Configure Personal, Team, or Enterprise guardrails in CI |
|
|
59
|
-
|
|
77
|
+
|
|
78
|
+
### Interactive Menu
|
|
79
|
+
If you run `outlier` directly, you'll be greeted with our frictionless UX:
|
|
80
|
+
```text
|
|
81
|
+
? Select outlier governance module:
|
|
82
|
+
── AUDIT ──
|
|
83
|
+
❯ Status Full audit (reliance + carbon + capabilities)
|
|
84
|
+
Authorship Human vs AI, per commit
|
|
85
|
+
Carbon Token waste + regional cost
|
|
86
|
+
Capabilities What your agents can reach
|
|
87
|
+
Policy Set guardrails / install the gate
|
|
88
|
+
── LEARN ──
|
|
89
|
+
Impact What happens over the next 5-10 years
|
|
90
|
+
Literature The academic foundation
|
|
91
|
+
Participate Contribute to the research
|
|
92
|
+
```
|
|
60
93
|
|
|
61
94
|
## Quickstart: Your First Audit
|
|
62
95
|
|
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.
|
|
168
|
+
version: "0.4.15",
|
|
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"
|
|
@@ -177,7 +177,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
177
177
|
"data"
|
|
178
178
|
],
|
|
179
179
|
scripts: {
|
|
180
|
-
build: "bun build ./src/cli.ts --target=node --outfile bin/outlier.js",
|
|
180
|
+
build: "bunx tsc --noEmit && bun build ./src/cli.ts --target=node --outfile bin/outlier.js",
|
|
181
181
|
test: "bun test",
|
|
182
182
|
start: "bun run src/cli.ts",
|
|
183
183
|
postinstall: "node bin/postinstall.js"
|
|
@@ -218,6 +218,9 @@ var require_package = __commonJS((exports, module) => {
|
|
|
218
218
|
};
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
+
// src/cli.ts
|
|
222
|
+
import os from "os";
|
|
223
|
+
|
|
221
224
|
// node_modules/@clack/core/dist/index.mjs
|
|
222
225
|
import { styleText } from "node:util";
|
|
223
226
|
import { stdout, stdin } from "node:process";
|
|
@@ -940,34 +943,16 @@ var T$1 = class T extends V {
|
|
|
940
943
|
}
|
|
941
944
|
}
|
|
942
945
|
};
|
|
943
|
-
|
|
944
|
-
class r extends V {
|
|
945
|
-
get cursor() {
|
|
946
|
-
return this.value ? 0 : 1;
|
|
947
|
-
}
|
|
948
|
-
get _value() {
|
|
949
|
-
return this.cursor === 0;
|
|
950
|
-
}
|
|
951
|
-
constructor(t2) {
|
|
952
|
-
super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
|
|
953
|
-
this.value = this._value;
|
|
954
|
-
}), this.on("confirm", (i) => {
|
|
955
|
-
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i, this.state = "submit", this.close();
|
|
956
|
-
}), this.on("cursor", () => {
|
|
957
|
-
this.value = !this.value;
|
|
958
|
-
});
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
946
|
var _ = {
|
|
962
947
|
Y: { type: "year", len: 4 },
|
|
963
948
|
M: { type: "month", len: 2 },
|
|
964
949
|
D: { type: "day", len: 2 }
|
|
965
950
|
};
|
|
966
|
-
function M(
|
|
967
|
-
return [...
|
|
951
|
+
function M(r) {
|
|
952
|
+
return [...r].map((t2) => _[t2]);
|
|
968
953
|
}
|
|
969
|
-
function P(
|
|
970
|
-
const i = new Intl.DateTimeFormat(
|
|
954
|
+
function P(r) {
|
|
955
|
+
const i = new Intl.DateTimeFormat(r, {
|
|
971
956
|
year: "numeric",
|
|
972
957
|
month: "2-digit",
|
|
973
958
|
day: "2-digit"
|
|
@@ -977,32 +962,32 @@ function P(r2) {
|
|
|
977
962
|
e.type === "literal" ? n = e.value.trim() || e.value : (e.type === "year" || e.type === "month" || e.type === "day") && s.push({ type: e.type, len: e.type === "year" ? 4 : 2 });
|
|
978
963
|
return { segments: s, separator: n };
|
|
979
964
|
}
|
|
980
|
-
function p(
|
|
981
|
-
return Number.parseInt((
|
|
965
|
+
function p(r) {
|
|
966
|
+
return Number.parseInt((r || "0").replace(/_/g, "0"), 10) || 0;
|
|
982
967
|
}
|
|
983
|
-
function f(
|
|
968
|
+
function f(r) {
|
|
984
969
|
return {
|
|
985
|
-
year: p(
|
|
986
|
-
month: p(
|
|
987
|
-
day: p(
|
|
970
|
+
year: p(r.year),
|
|
971
|
+
month: p(r.month),
|
|
972
|
+
day: p(r.day)
|
|
988
973
|
};
|
|
989
974
|
}
|
|
990
|
-
function c(
|
|
991
|
-
return new Date(
|
|
975
|
+
function c(r, t2) {
|
|
976
|
+
return new Date(r || 2001, t2 || 1, 0).getDate();
|
|
992
977
|
}
|
|
993
|
-
function b(
|
|
994
|
-
const { year: t2, month: i, day: s } = f(
|
|
978
|
+
function b(r) {
|
|
979
|
+
const { year: t2, month: i, day: s } = f(r);
|
|
995
980
|
if (!t2 || t2 < 0 || t2 > 9999 || !i || i < 1 || i > 12 || !s || s < 1)
|
|
996
981
|
return;
|
|
997
982
|
const n = new Date(Date.UTC(t2, i - 1, s));
|
|
998
983
|
if (!(n.getUTCFullYear() !== t2 || n.getUTCMonth() !== i - 1 || n.getUTCDate() !== s))
|
|
999
984
|
return { year: t2, month: i, day: s };
|
|
1000
985
|
}
|
|
1001
|
-
function C(
|
|
1002
|
-
const t2 = b(
|
|
986
|
+
function C(r) {
|
|
987
|
+
const t2 = b(r);
|
|
1003
988
|
return t2 ? new Date(Date.UTC(t2.year, t2.month - 1, t2.day)) : undefined;
|
|
1004
989
|
}
|
|
1005
|
-
function T2(
|
|
990
|
+
function T2(r, t2, i, s) {
|
|
1006
991
|
const n = i ? {
|
|
1007
992
|
year: i.getUTCFullYear(),
|
|
1008
993
|
month: i.getUTCMonth() + 1,
|
|
@@ -1012,7 +997,7 @@ function T2(r2, t2, i, s) {
|
|
|
1012
997
|
month: s.getUTCMonth() + 1,
|
|
1013
998
|
day: s.getUTCDate()
|
|
1014
999
|
} : null;
|
|
1015
|
-
return
|
|
1000
|
+
return r === "year" ? { min: n?.year ?? 1, max: e?.year ?? 9999 } : r === "month" ? {
|
|
1016
1001
|
min: n && t2.year === n.year ? n.month : 1,
|
|
1017
1002
|
max: e && t2.year === e.year ? e.month : 12
|
|
1018
1003
|
} : {
|
|
@@ -1185,26 +1170,26 @@ var u$1 = class u extends V {
|
|
|
1185
1170
|
cursor = 0;
|
|
1186
1171
|
#t;
|
|
1187
1172
|
getGroupItems(t2) {
|
|
1188
|
-
return this.options.filter((
|
|
1173
|
+
return this.options.filter((r) => r.group === t2);
|
|
1189
1174
|
}
|
|
1190
1175
|
isGroupSelected(t2) {
|
|
1191
|
-
const
|
|
1192
|
-
return e === undefined ? false :
|
|
1176
|
+
const r = this.getGroupItems(t2), e = this.value;
|
|
1177
|
+
return e === undefined ? false : r.every((s) => e.includes(s.value));
|
|
1193
1178
|
}
|
|
1194
1179
|
toggleValue() {
|
|
1195
1180
|
const t2 = this.options[this.cursor];
|
|
1196
1181
|
if (this.value === undefined && (this.value = []), t2.group === true) {
|
|
1197
|
-
const
|
|
1198
|
-
this.isGroupSelected(
|
|
1182
|
+
const r = t2.value, e = this.getGroupItems(r);
|
|
1183
|
+
this.isGroupSelected(r) ? this.value = this.value.filter((s) => e.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...e.map((s) => s.value)], this.value = Array.from(new Set(this.value));
|
|
1199
1184
|
} else {
|
|
1200
|
-
const
|
|
1201
|
-
this.value =
|
|
1185
|
+
const r = this.value.includes(t2.value);
|
|
1186
|
+
this.value = r ? this.value.filter((e) => e !== t2.value) : [...this.value, t2.value];
|
|
1202
1187
|
}
|
|
1203
1188
|
}
|
|
1204
1189
|
constructor(t2) {
|
|
1205
1190
|
super(t2, false);
|
|
1206
|
-
const { options:
|
|
1207
|
-
this.#t = t2.selectableGroups !== false, this.options = Object.entries(
|
|
1191
|
+
const { options: r } = t2;
|
|
1192
|
+
this.#t = t2.selectableGroups !== false, this.options = Object.entries(r).flatMap(([e, s]) => [
|
|
1208
1193
|
{ value: e, group: true, label: e },
|
|
1209
1194
|
...s.map((i) => ({ ...i, group: e }))
|
|
1210
1195
|
]), this.value = [...t2.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === t2.cursorAt), this.#t ? 0 : 1), this.on("cursor", (e) => {
|
|
@@ -1242,10 +1227,10 @@ class h extends V {
|
|
|
1242
1227
|
const t2 = this.userInput;
|
|
1243
1228
|
if (this.cursor >= t2.length)
|
|
1244
1229
|
return `${t2}█`;
|
|
1245
|
-
const s = t2.slice(0, this.cursor),
|
|
1246
|
-
return
|
|
1230
|
+
const s = t2.slice(0, this.cursor), r = t2[this.cursor], i = t2.slice(this.cursor + 1);
|
|
1231
|
+
return r === `
|
|
1247
1232
|
` ? `${s}█
|
|
1248
|
-
${i}` : `${s}${styleText("inverse",
|
|
1233
|
+
${i}` : `${s}${styleText("inverse", r)}${i}`;
|
|
1249
1234
|
}
|
|
1250
1235
|
get cursor() {
|
|
1251
1236
|
return this._cursor;
|
|
@@ -1278,8 +1263,8 @@ ${i}` : `${s}${styleText("inverse", r2)}${i}`;
|
|
|
1278
1263
|
if (this.#s)
|
|
1279
1264
|
return this.focused === "submit" ? true : (this.#r(`
|
|
1280
1265
|
`), this._cursor++, false);
|
|
1281
|
-
const
|
|
1282
|
-
return this.#t = true,
|
|
1266
|
+
const r = this.#t;
|
|
1267
|
+
return this.#t = true, r && this.cursor === this.userInput.length ? (this.userInput[this.cursor - 1] === `
|
|
1283
1268
|
` && (this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--), true) : (this.#r(`
|
|
1284
1269
|
`), this._cursor++, false);
|
|
1285
1270
|
}
|
|
@@ -1288,12 +1273,12 @@ ${i}` : `${s}${styleText("inverse", r2)}${i}`;
|
|
|
1288
1273
|
super({
|
|
1289
1274
|
...t2,
|
|
1290
1275
|
initialUserInput: s
|
|
1291
|
-
}, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (
|
|
1276
|
+
}, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (r, i) => {
|
|
1292
1277
|
if (i?.name && o$1.has(i.name)) {
|
|
1293
1278
|
this.#t = false, this.#i(i.name);
|
|
1294
1279
|
return;
|
|
1295
1280
|
}
|
|
1296
|
-
if (
|
|
1281
|
+
if (r === "\t" && this.#s) {
|
|
1297
1282
|
this.focused = this.focused === "editor" ? "submit" : "editor";
|
|
1298
1283
|
return;
|
|
1299
1284
|
}
|
|
@@ -1306,10 +1291,10 @@ ${i}` : `${s}${styleText("inverse", r2)}${i}`;
|
|
|
1306
1291
|
this._setUserInput(this.userInput.slice(0, this.cursor) + this.userInput.slice(this.cursor + 1));
|
|
1307
1292
|
return;
|
|
1308
1293
|
}
|
|
1309
|
-
|
|
1294
|
+
r && (this.#s && this.focused === "submit" && (this.focused = "editor"), this.#r(r ?? ""), this._cursor++);
|
|
1310
1295
|
}
|
|
1311
|
-
}), this.on("userInput", (
|
|
1312
|
-
this._setValue(
|
|
1296
|
+
}), this.on("userInput", (r) => {
|
|
1297
|
+
this._setValue(r);
|
|
1313
1298
|
}), this.on("finalize", () => {
|
|
1314
1299
|
this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
|
|
1315
1300
|
});
|
|
@@ -1349,8 +1334,8 @@ class n extends V {
|
|
|
1349
1334
|
const t2 = this.userInput;
|
|
1350
1335
|
if (this.cursor >= t2.length)
|
|
1351
1336
|
return `${this.userInput}█`;
|
|
1352
|
-
const e = t2.slice(0, this.cursor), [s, ...
|
|
1353
|
-
return `${e}${styleText("inverse", s)}${
|
|
1337
|
+
const e = t2.slice(0, this.cursor), [s, ...r] = t2.slice(this.cursor);
|
|
1338
|
+
return `${e}${styleText("inverse", s)}${r.join("")}`;
|
|
1354
1339
|
}
|
|
1355
1340
|
get cursor() {
|
|
1356
1341
|
return this._cursor;
|
|
@@ -1484,41 +1469,6 @@ var limitOptions = ({
|
|
|
1484
1469
|
b2.push(n2);
|
|
1485
1470
|
return u3 && b2.push(C2), b2;
|
|
1486
1471
|
};
|
|
1487
|
-
var confirm = (i) => {
|
|
1488
|
-
const a2 = i.active ?? "Yes", s = i.inactive ?? "No";
|
|
1489
|
-
return new r({
|
|
1490
|
-
active: a2,
|
|
1491
|
-
inactive: s,
|
|
1492
|
-
signal: i.signal,
|
|
1493
|
-
input: i.input,
|
|
1494
|
-
output: i.output,
|
|
1495
|
-
initialValue: i.initialValue ?? true,
|
|
1496
|
-
render() {
|
|
1497
|
-
const e = i.withGuide ?? settings.withGuide, u3 = `${symbol(this.state)} `, l2 = e ? `${styleText2("gray", S_BAR)} ` : "", f2 = wrapTextWithPrefix(i.output, i.message, l2, u3), o2 = `${e ? `${styleText2("gray", S_BAR)}
|
|
1498
|
-
` : ""}${f2}
|
|
1499
|
-
`, c2 = this.value ? a2 : s;
|
|
1500
|
-
switch (this.state) {
|
|
1501
|
-
case "submit": {
|
|
1502
|
-
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
1503
|
-
return `${o2}${r2}${styleText2("dim", c2)}`;
|
|
1504
|
-
}
|
|
1505
|
-
case "cancel": {
|
|
1506
|
-
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
1507
|
-
return `${o2}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
|
|
1508
|
-
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1509
|
-
}
|
|
1510
|
-
default: {
|
|
1511
|
-
const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e ? styleText2("cyan", S_BAR_END) : "";
|
|
1512
|
-
return `${o2}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i.vertical ? e ? `
|
|
1513
|
-
${styleText2("cyan", S_BAR)} ` : `
|
|
1514
|
-
` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
|
|
1515
|
-
${g2}
|
|
1516
|
-
`;
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
}).prompt();
|
|
1521
|
-
};
|
|
1522
1472
|
var MULTISELECT_INSTRUCTIONS = [
|
|
1523
1473
|
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
1524
1474
|
`${styleText2("dim", "Space:")} select`,
|
|
@@ -1941,7 +1891,6 @@ async function getCapabilitiesStats(repoPath = process.cwd(), homeDirPath = home
|
|
|
1941
1891
|
// src/cli.ts
|
|
1942
1892
|
import { writeFileSync, chmodSync, existsSync as existsSync2 } from "fs";
|
|
1943
1893
|
import { join as join3 } from "path";
|
|
1944
|
-
import os from "os";
|
|
1945
1894
|
var ASCII_LOGO = `
|
|
1946
1895
|
____ _ _ _____ _ ___ _____ ____
|
|
1947
1896
|
/ __ \\| | | |_ _| | |_ _| ___| _ \\
|
|
@@ -1950,39 +1899,15 @@ var ASCII_LOGO = `
|
|
|
1950
1899
|
| |__| | _ | | | | _ || || |___| | \\ \\
|
|
1951
1900
|
\\____/|_| |_| |_| |_| |_|___|_____|_| \\_\\
|
|
1952
1901
|
`;
|
|
1902
|
+
var finalReceipt = "";
|
|
1953
1903
|
async function runOnboarding() {
|
|
1954
1904
|
console.clear();
|
|
1955
1905
|
console.log(import_picocolors.default.cyan(ASCII_LOGO));
|
|
1956
1906
|
intro(import_picocolors.default.inverse(" outlier: Welcome "));
|
|
1957
|
-
note(`Outlier is a local-first Policy Engine & Governance Framework for AI Engineering.
|
|
1958
|
-
|
|
1959
|
-
Our mission is AI Safety for developers:
|
|
1960
|
-
As agents (Cursor, Copilot, Claude) write more of our code, we lose visibility into:
|
|
1961
|
-
1. Deskilling Risk (Are we becoming spectators in our own codebase?)
|
|
1962
|
-
2. Carbon Cost (What is the true regional energy cost of token caching?)
|
|
1963
|
-
3. Capability Drift (What hidden skills and external tools are our agents using?)
|
|
1964
|
-
|
|
1965
|
-
We built Outlier to enforce Zero-Trust and protect Human Mastery. You are in control.`, "The Problem: AI Safety in Development");
|
|
1966
1907
|
note(`Outlier operates entirely on your machine.
|
|
1967
1908
|
- Local Only: No API keys. No cloud telemetry. No data leaves your machine.
|
|
1968
|
-
- Native Auditing: We
|
|
1969
|
-
- Actionable Policies:
|
|
1970
|
-
note(`Available Commands:
|
|
1971
|
-
- status: Run a full system audit (Reliance, Carbon, Capabilities)
|
|
1972
|
-
- policy: Configure team/enterprise guardrails and CLI blockers
|
|
1973
|
-
- carbon: View isolated token caching metrics and regional counterfactuals
|
|
1974
|
-
- authorship: View Git authorship ratio (Human vs AI)`, "How it is used");
|
|
1975
|
-
note(`When you start the audit, Outlier will locally parse your Git commits to identify AI co-authorship and cross-reference your agent logs to calculate token waste.
|
|
1976
|
-
|
|
1977
|
-
The results will assign you a "vibe" and evaluate if you are at risk of deskilling.`, "What to Expect");
|
|
1978
|
-
const ready = await confirm({
|
|
1979
|
-
message: "Are you ready to run your first Governance Audit and measure your AI reliance?",
|
|
1980
|
-
initialValue: true
|
|
1981
|
-
});
|
|
1982
|
-
if (isCancel(ready) || !ready) {
|
|
1983
|
-
cancel("Onboarding paused. Run outlier again when you are ready.");
|
|
1984
|
-
process.exit(0);
|
|
1985
|
-
}
|
|
1909
|
+
- Native Auditing: We read your local \`~/.claude\` logs and \`.git/\` commit history.
|
|
1910
|
+
- Actionable Policies: Enforce rules locally via terminal or Git hooks.`, "Privacy & Zero-Trust Principles");
|
|
1986
1911
|
const configPath = join3(os.homedir(), ".outlier_config");
|
|
1987
1912
|
writeFileSync(configPath, JSON.stringify({ onboarded: true, date: new Date().toISOString() }));
|
|
1988
1913
|
}
|
|
@@ -2015,27 +1940,7 @@ COMMANDS:`));
|
|
|
2015
1940
|
}
|
|
2016
1941
|
intro(import_picocolors.default.inverse(" outlier "));
|
|
2017
1942
|
if (!action || action === "audit") {
|
|
2018
|
-
|
|
2019
|
-
action = await select({
|
|
2020
|
-
message: "Select outlier governance module:",
|
|
2021
|
-
options: [
|
|
2022
|
-
{ value: "status", label: "Status Report", hint: "Run full AI reliance and capability audit" },
|
|
2023
|
-
{ value: "capabilities", label: "Capabilities Map", hint: "Audit active MCPs, skills, and orchestrations" },
|
|
2024
|
-
{ value: "authorship", label: "Code Durability", hint: "Scan git history for AI Code Reliance & Hallucination Risk" },
|
|
2025
|
-
{ value: "carbon", label: "Cache Bloat", hint: "Scan local logs for context waste & token costs" },
|
|
2026
|
-
{ value: "policy", label: "Policy Profiles", hint: "Set Personal, Team, or Enterprise guardrails in CI" },
|
|
2027
|
-
{ value: "impact", label: "Impact Horizon", hint: "What do you lose and gain in the next 5-10 years?" },
|
|
2028
|
-
{ value: "knowledge", label: "Literature Base", hint: "Explore references and the core academic foundation" },
|
|
2029
|
-
{ value: "participate", label: "Participate", hint: "Contribute to the literature on AI deskilling" }
|
|
2030
|
-
]
|
|
2031
|
-
});
|
|
2032
|
-
if (isCancel(action)) {
|
|
2033
|
-
cancel("Operation cancelled.");
|
|
2034
|
-
process.exit(0);
|
|
2035
|
-
}
|
|
2036
|
-
} else {
|
|
2037
|
-
action = "status";
|
|
2038
|
-
}
|
|
1943
|
+
action = "status";
|
|
2039
1944
|
}
|
|
2040
1945
|
const s = spinner();
|
|
2041
1946
|
if (action === "carbon") {
|
|
@@ -2202,7 +2107,7 @@ ${import_picocolors.default.bold("Governance:")} ${ruleFailures > 0 ? import_pic
|
|
|
2202
2107
|
const dateStr = new Date().toLocaleDateString("en-US", { month: "short", day: "2-digit", year: "numeric" }).toUpperCase();
|
|
2203
2108
|
const timeStr = new Date().toLocaleTimeString("en-US", { hour12: false });
|
|
2204
2109
|
const repoName = process.cwd().split("/").pop() || "Unknown";
|
|
2205
|
-
|
|
2110
|
+
finalReceipt = `
|
|
2206
2111
|
${import_picocolors.default.dim("┌────────────────────────────────────────────────────────")}
|
|
2207
2112
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("█▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█")} ${import_picocolors.default.bold(":: THERMAL AUDIT RECEIPT")}
|
|
2208
2113
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan("█▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄")} ${import_picocolors.default.dim(`:: TIMESTAMP: ${dateStr}`)}
|
|
@@ -2236,7 +2141,7 @@ ${import_picocolors.default.bold("Governance:")} ${ruleFailures > 0 ? import_pic
|
|
|
2236
2141
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.italic(import_picocolors.default.dim("human mastery is the only true moat."))}
|
|
2237
2142
|
${import_picocolors.default.dim("│")}
|
|
2238
2143
|
${import_picocolors.default.dim("│")} ${import_picocolors.default.bold(import_picocolors.default.cyan("***STAY VIGILANT***"))}
|
|
2239
|
-
${import_picocolors.default.dim("└────────────────────────────────────────────────────────")}
|
|
2144
|
+
${import_picocolors.default.dim("└────────────────────────────────────────────────────────")}`;
|
|
2240
2145
|
} else {
|
|
2241
2146
|
note(`status: ${authPct} AI Reliance | ${cachePct}% Cache Bloat | ${co2Str}`, `${import_picocolors.default.bold("[outlier]")} CI/CD Audit`);
|
|
2242
2147
|
}
|
|
@@ -2429,12 +2334,22 @@ Read the full academic foundation at: ${import_picocolors.default.underline("htt
|
|
|
2429
2334
|
`);
|
|
2430
2335
|
}
|
|
2431
2336
|
outro("Local telemetry run completed. No data left your machine.");
|
|
2432
|
-
|
|
2337
|
+
if (typeof finalReceipt !== "undefined" && finalReceipt) {
|
|
2338
|
+
console.log(finalReceipt);
|
|
2339
|
+
}
|
|
2340
|
+
if (action === "status") {
|
|
2341
|
+
console.log("");
|
|
2342
|
+
console.log(import_picocolors.default.bold(" Explore Outlier:"));
|
|
2343
|
+
console.log(import_picocolors.default.dim(" ────────────────────────────────────────────────────────────"));
|
|
2344
|
+
console.log(` ${import_picocolors.default.cyan("outlier policy")} Configure CI/CD guardrails and thresholds`);
|
|
2345
|
+
console.log(` ${import_picocolors.default.cyan("outlier capabilities")} Audit active MCPs, skills, and orchestrations`);
|
|
2346
|
+
console.log(` ${import_picocolors.default.cyan("outlier impact")} See the compounding horizon of AI Deskilling`);
|
|
2347
|
+
console.log(` ${import_picocolors.default.cyan("outlier participate")} Help build the academic literature`);
|
|
2348
|
+
console.log(import_picocolors.default.dim(` ────────────────────────────────────────────────────────────
|
|
2349
|
+
`));
|
|
2350
|
+
console.log(import_picocolors.default.bold(import_picocolors.default.green(" └ Prove Your Mastery: ")) + import_picocolors.default.underline(`https://x.com/intent/tweet?text=${encodeURIComponent(`I just audited my codebase for AI reliance and deskilling risk. What does your repo score?
|
|
2433
2351
|
|
|
2434
2352
|
\uD83D\uDCCF #Outlier`)}`));
|
|
2435
|
-
if (action === "status") {
|
|
2436
|
-
console.log(import_picocolors.default.dim(`└ Have thoughts on AI deskilling? Tell us: `) + import_picocolors.default.cyan(`outlier participate`));
|
|
2437
|
-
console.log(import_picocolors.default.dim(`└ Keep your local policies updated: `) + import_picocolors.default.cyan(`outlier update`));
|
|
2438
2353
|
}
|
|
2439
2354
|
}
|
|
2440
2355
|
main().catch(console.error);
|
package/bin/postinstall.js
CHANGED
|
@@ -9,9 +9,12 @@ console.log(dim('─────────────────────
|
|
|
9
9
|
console.log('To start the interactive wizard and audit your codebase, type:\n');
|
|
10
10
|
console.log(` ${cyan('outlier')}\n`);
|
|
11
11
|
console.log('Available Commands:');
|
|
12
|
-
console.log(` ${cyan('outlier status')}
|
|
13
|
-
console.log(` ${cyan('outlier
|
|
12
|
+
console.log(` ${cyan('outlier status')} Run full AI reliance & capability audit`);
|
|
13
|
+
console.log(` ${cyan('outlier authorship')} Scan git history for AI co-authorship ratio`);
|
|
14
|
+
console.log(` ${cyan('outlier carbon')} Scan local logs for token waste & carbon cost`);
|
|
15
|
+
console.log(` ${cyan('outlier capabilities')} Audit active MCPs, skills, and orchestrations`);
|
|
16
|
+
console.log(` ${cyan('outlier policy')} Configure CI/CD guardrails and thresholds`);
|
|
17
|
+
console.log(` ${cyan('outlier impact')} See the compounding horizon of AI Deskilling`);
|
|
14
18
|
console.log(` ${cyan('outlier knowledge')} Explore core literature and METR references`);
|
|
15
19
|
console.log(` ${cyan('outlier participate')} Help build the literature on AI deskilling`);
|
|
16
|
-
console.log(` ${cyan('outlier help')} See all available commands`);
|
|
17
20
|
console.log(dim('────────────────────────────────────────────────────────────\n'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rosh100yx/outlier",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.15",
|
|
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"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"data"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build": "bun build ./src/cli.ts --target=node --outfile bin/outlier.js",
|
|
15
|
+
"build": "bunx tsc --noEmit && bun build ./src/cli.ts --target=node --outfile bin/outlier.js",
|
|
16
16
|
"test": "bun test",
|
|
17
17
|
"start": "bun run src/cli.ts",
|
|
18
18
|
"postinstall": "node bin/postinstall.js"
|
package/src/cli.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import os from 'os';
|
|
2
3
|
import { intro, outro, select, spinner, isCancel, cancel, note, text, confirm } from '@clack/prompts';
|
|
3
4
|
import pc from 'picocolors';
|
|
4
5
|
import { getAuthorshipStats } from './git';
|
|
@@ -6,7 +7,6 @@ import { getCarbonStats } from './carbon';
|
|
|
6
7
|
import { getCapabilitiesStats } from './capabilities';
|
|
7
8
|
import { writeFileSync, chmodSync, existsSync } from 'fs';
|
|
8
9
|
import { join } from 'path';
|
|
9
|
-
import { execSync } from 'child_process';
|
|
10
10
|
|
|
11
11
|
const ASCII_LOGO = `
|
|
12
12
|
____ _ _ _____ _ ___ _____ ____
|
|
@@ -17,61 +17,21 @@ const ASCII_LOGO = `
|
|
|
17
17
|
\\____/|_| |_| |_| |_| |_|___|_____|_| \\_\\
|
|
18
18
|
`;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
import { confirm } from '@clack/prompts';
|
|
20
|
+
let finalReceipt = '';
|
|
22
21
|
|
|
23
22
|
async function runOnboarding() {
|
|
24
23
|
console.clear();
|
|
25
24
|
console.log(pc.cyan(ASCII_LOGO));
|
|
26
25
|
intro(pc.inverse(' outlier: Welcome '));
|
|
27
26
|
|
|
28
|
-
note(
|
|
29
|
-
`Outlier is a local-first Policy Engine & Governance Framework for AI Engineering.
|
|
30
|
-
|
|
31
|
-
Our mission is AI Safety for developers:
|
|
32
|
-
As agents (Cursor, Copilot, Claude) write more of our code, we lose visibility into:
|
|
33
|
-
1. Deskilling Risk (Are we becoming spectators in our own codebase?)
|
|
34
|
-
2. Carbon Cost (What is the true regional energy cost of token caching?)
|
|
35
|
-
3. Capability Drift (What hidden skills and external tools are our agents using?)
|
|
36
|
-
|
|
37
|
-
We built Outlier to enforce Zero-Trust and protect Human Mastery. You are in control.`,
|
|
38
|
-
'The Problem: AI Safety in Development'
|
|
39
|
-
);
|
|
40
|
-
|
|
41
27
|
note(
|
|
42
28
|
`Outlier operates entirely on your machine.
|
|
43
29
|
- Local Only: No API keys. No cloud telemetry. No data leaves your machine.
|
|
44
|
-
- Native Auditing: We
|
|
45
|
-
- Actionable Policies:
|
|
30
|
+
- Native Auditing: We read your local \`~/.claude\` logs and \`.git/\` commit history.
|
|
31
|
+
- Actionable Policies: Enforce rules locally via terminal or Git hooks.`,
|
|
46
32
|
'Privacy & Zero-Trust Principles'
|
|
47
33
|
);
|
|
48
34
|
|
|
49
|
-
note(
|
|
50
|
-
`Available Commands:
|
|
51
|
-
- status: Run a full system audit (Reliance, Carbon, Capabilities)
|
|
52
|
-
- policy: Configure team/enterprise guardrails and CLI blockers
|
|
53
|
-
- carbon: View isolated token caching metrics and regional counterfactuals
|
|
54
|
-
- authorship: View Git authorship ratio (Human vs AI)`,
|
|
55
|
-
'How it is used'
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
note(
|
|
59
|
-
`When you start the audit, Outlier will locally parse your Git commits to identify AI co-authorship and cross-reference your agent logs to calculate token waste.
|
|
60
|
-
|
|
61
|
-
The results will assign you a "vibe" and evaluate if you are at risk of deskilling.`,
|
|
62
|
-
'What to Expect'
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const ready = await confirm({
|
|
66
|
-
message: 'Are you ready to run your first Governance Audit and measure your AI reliance?',
|
|
67
|
-
initialValue: true,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (isCancel(ready) || !ready) {
|
|
71
|
-
cancel('Onboarding paused. Run outlier again when you are ready.');
|
|
72
|
-
process.exit(0);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
35
|
const configPath = join(os.homedir(), '.outlier_config');
|
|
76
36
|
writeFileSync(configPath, JSON.stringify({ onboarded: true, date: new Date().toISOString() }));
|
|
77
37
|
}
|
|
@@ -107,28 +67,7 @@ async function main() {
|
|
|
107
67
|
intro(pc.inverse(' outlier '));
|
|
108
68
|
|
|
109
69
|
if (!action || action === 'audit') {
|
|
110
|
-
|
|
111
|
-
action = await select({
|
|
112
|
-
message: 'Select outlier governance module:',
|
|
113
|
-
options: [
|
|
114
|
-
{ value: 'status', label: 'Status Report', hint: 'Run full AI reliance and capability audit' },
|
|
115
|
-
{ value: 'capabilities', label: 'Capabilities Map', hint: 'Audit active MCPs, skills, and orchestrations' },
|
|
116
|
-
{ value: 'authorship', label: 'Code Durability', hint: 'Scan git history for AI Code Reliance & Hallucination Risk' },
|
|
117
|
-
{ value: 'carbon', label: 'Cache Bloat', hint: 'Scan local logs for context waste & token costs' },
|
|
118
|
-
{ value: 'policy', label: 'Policy Profiles', hint: 'Set Personal, Team, or Enterprise guardrails in CI' },
|
|
119
|
-
{ value: 'impact', label: 'Impact Horizon', hint: 'What do you lose and gain in the next 5-10 years?' },
|
|
120
|
-
{ value: 'knowledge', label: 'Literature Base', hint: 'Explore references and the core academic foundation' },
|
|
121
|
-
{ value: 'participate', label: 'Participate', hint: 'Contribute to the literature on AI deskilling' }
|
|
122
|
-
],
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
if (isCancel(action)) {
|
|
126
|
-
cancel('Operation cancelled.');
|
|
127
|
-
process.exit(0);
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
action = 'status'; // Map the 'audit' alias directly to status for CI
|
|
131
|
-
}
|
|
70
|
+
action = 'status'; // Auto-run the main audit loop for highest TTV
|
|
132
71
|
}
|
|
133
72
|
|
|
134
73
|
const s = spinner();
|
|
@@ -323,7 +262,7 @@ ${pc.bold('Governance:')} ${ruleFailures > 0 ? pc.red(`${failIcon} ${ruleFailure
|
|
|
323
262
|
const timeStr = new Date().toLocaleTimeString('en-US', { hour12: false });
|
|
324
263
|
const repoName = process.cwd().split('/').pop() || 'Unknown';
|
|
325
264
|
|
|
326
|
-
|
|
265
|
+
finalReceipt = `
|
|
327
266
|
${pc.dim('┌────────────────────────────────────────────────────────')}
|
|
328
267
|
${pc.dim('│')} ${pc.cyan('█▀█ █░█ ▀█▀ █░░ █ █▀▀ █▀█')} ${pc.bold(':: THERMAL AUDIT RECEIPT')}
|
|
329
268
|
${pc.dim('│')} ${pc.cyan('█▄█ █▄█ ░█░ █▄▄ █ ██▄ █▀▄')} ${pc.dim(`:: TIMESTAMP: ${dateStr}`)}
|
|
@@ -353,7 +292,7 @@ ${pc.bold('Governance:')} ${ruleFailures > 0 ? pc.red(`${failIcon} ${ruleFailure
|
|
|
353
292
|
${pc.dim('│')} ${pc.italic(pc.dim('human mastery is the only true moat.'))}
|
|
354
293
|
${pc.dim('│')}
|
|
355
294
|
${pc.dim('│')} ${pc.bold(pc.cyan('***STAY VIGILANT***'))}
|
|
356
|
-
${pc.dim('└────────────────────────────────────────────────────────')}
|
|
295
|
+
${pc.dim('└────────────────────────────────────────────────────────')}`;
|
|
357
296
|
} else {
|
|
358
297
|
note(
|
|
359
298
|
`status: ${authPct} AI Reliance | ${cachePct}% Cache Bloat | ${co2Str}`,
|
|
@@ -558,22 +497,22 @@ Artifact: ${pc.cyan(reportPath)}`,
|
|
|
558
497
|
|
|
559
498
|
outro('Local telemetry run completed. No data left your machine.');
|
|
560
499
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
pc.dim(
|
|
565
|
-
`└ Share your audit: https://x.com/intent/tweet?text=${encodeURIComponent(
|
|
566
|
-
'I just audited my codebase for AI reliance and deskilling risk. What does your repo score?\n\n📏 #Outlier'
|
|
567
|
-
)}`
|
|
568
|
-
)
|
|
569
|
-
);
|
|
500
|
+
if (typeof finalReceipt !== 'undefined' && finalReceipt) {
|
|
501
|
+
console.log(finalReceipt);
|
|
502
|
+
}
|
|
570
503
|
|
|
571
504
|
if (action === 'status') {
|
|
505
|
+
console.log('');
|
|
506
|
+
console.log(pc.bold(' Explore Outlier:'));
|
|
507
|
+
console.log(pc.dim(' ────────────────────────────────────────────────────────────'));
|
|
508
|
+
console.log(` ${pc.cyan('outlier policy')} Configure CI/CD guardrails and thresholds`);
|
|
509
|
+
console.log(` ${pc.cyan('outlier capabilities')} Audit active MCPs, skills, and orchestrations`);
|
|
510
|
+
console.log(` ${pc.cyan('outlier impact')} See the compounding horizon of AI Deskilling`);
|
|
511
|
+
console.log(` ${pc.cyan('outlier participate')} Help build the academic literature`);
|
|
512
|
+
console.log(pc.dim(' ────────────────────────────────────────────────────────────\n'));
|
|
513
|
+
|
|
572
514
|
console.log(
|
|
573
|
-
pc.
|
|
574
|
-
);
|
|
575
|
-
console.log(
|
|
576
|
-
pc.dim(`└ Keep your local policies updated: `) + pc.cyan(`outlier update`)
|
|
515
|
+
pc.bold(pc.green(' └ Prove Your Mastery: ')) + pc.underline(`https://x.com/intent/tweet?text=${encodeURIComponent('I just audited my codebase for AI reliance and deskilling risk. What does your repo score?\n\n📏 #Outlier')}`)
|
|
577
516
|
);
|
|
578
517
|
}
|
|
579
518
|
}
|