@rosh100yx/outlier 0.4.15 → 0.4.16
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 +20 -22
- package/bin/outlier.js +107 -40
- package/package.json +1 -1
- package/src/cli.ts +20 -0
package/README.md
CHANGED
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
<p>
|
|
15
15
|
<b>Get Started Instantly:</b><br/>
|
|
16
|
-
<code>
|
|
17
|
-
<code>outlier status</code>
|
|
16
|
+
<code>npx @rosh100yx/outlier@latest</code>
|
|
18
17
|
</p>
|
|
19
18
|
|
|
20
19
|
<br/>
|
|
@@ -68,27 +67,26 @@
|
|
|
68
67
|
## Commands
|
|
69
68
|
| Command | Purpose |
|
|
70
69
|
|---------|---------|
|
|
71
|
-
| `outlier` |
|
|
72
|
-
| `outlier
|
|
73
|
-
| `outlier
|
|
74
|
-
| `outlier
|
|
75
|
-
| `outlier
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
If you run `outlier` directly, you'll be greeted with our frictionless UX:
|
|
70
|
+
| `npx @rosh100yx/outlier` | Run the full AI reliance & capability audit |
|
|
71
|
+
| `npx @rosh100yx/outlier authorship` | Scan git history for AI co-authorship ratio |
|
|
72
|
+
| `npx @rosh100yx/outlier carbon` | Scan local logs for context waste & token costs |
|
|
73
|
+
| `npx @rosh100yx/outlier capabilities` | Audit active MCPs, skills, and orchestrations |
|
|
74
|
+
| `npx @rosh100yx/outlier policy` | Configure Personal, Team, or Enterprise guardrails in CI |
|
|
75
|
+
|
|
76
|
+
### The UX Flow
|
|
77
|
+
If you run `npx @rosh100yx/outlier` directly, you'll instantly get your Thermal Receipt and a simple list of follow-up commands:
|
|
80
78
|
```text
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
└────────────────────────────────────────────────────────┘
|
|
80
|
+
|
|
81
|
+
Explore Outlier:
|
|
82
|
+
────────────────────────────────────────────────────────────
|
|
83
|
+
outlier policy Configure CI/CD guardrails and thresholds
|
|
84
|
+
outlier capabilities Audit active MCPs, skills, and orchestrations
|
|
85
|
+
outlier impact See the compounding horizon of AI Deskilling
|
|
86
|
+
outlier participate Help build the academic literature
|
|
87
|
+
────────────────────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
└ Prove Your Mastery: https://x.com/intent/tweet?...
|
|
92
90
|
```
|
|
93
91
|
|
|
94
92
|
## Quickstart: Your First Audit
|
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.16",
|
|
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"
|
|
@@ -943,16 +943,34 @@ var T$1 = class T extends V {
|
|
|
943
943
|
}
|
|
944
944
|
}
|
|
945
945
|
};
|
|
946
|
+
|
|
947
|
+
class r extends V {
|
|
948
|
+
get cursor() {
|
|
949
|
+
return this.value ? 0 : 1;
|
|
950
|
+
}
|
|
951
|
+
get _value() {
|
|
952
|
+
return this.cursor === 0;
|
|
953
|
+
}
|
|
954
|
+
constructor(t2) {
|
|
955
|
+
super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
|
|
956
|
+
this.value = this._value;
|
|
957
|
+
}), this.on("confirm", (i) => {
|
|
958
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i, this.state = "submit", this.close();
|
|
959
|
+
}), this.on("cursor", () => {
|
|
960
|
+
this.value = !this.value;
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
}
|
|
946
964
|
var _ = {
|
|
947
965
|
Y: { type: "year", len: 4 },
|
|
948
966
|
M: { type: "month", len: 2 },
|
|
949
967
|
D: { type: "day", len: 2 }
|
|
950
968
|
};
|
|
951
|
-
function M(
|
|
952
|
-
return [...
|
|
969
|
+
function M(r2) {
|
|
970
|
+
return [...r2].map((t2) => _[t2]);
|
|
953
971
|
}
|
|
954
|
-
function P(
|
|
955
|
-
const i = new Intl.DateTimeFormat(
|
|
972
|
+
function P(r2) {
|
|
973
|
+
const i = new Intl.DateTimeFormat(r2, {
|
|
956
974
|
year: "numeric",
|
|
957
975
|
month: "2-digit",
|
|
958
976
|
day: "2-digit"
|
|
@@ -962,32 +980,32 @@ function P(r) {
|
|
|
962
980
|
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 });
|
|
963
981
|
return { segments: s, separator: n };
|
|
964
982
|
}
|
|
965
|
-
function p(
|
|
966
|
-
return Number.parseInt((
|
|
983
|
+
function p(r2) {
|
|
984
|
+
return Number.parseInt((r2 || "0").replace(/_/g, "0"), 10) || 0;
|
|
967
985
|
}
|
|
968
|
-
function f(
|
|
986
|
+
function f(r2) {
|
|
969
987
|
return {
|
|
970
|
-
year: p(
|
|
971
|
-
month: p(
|
|
972
|
-
day: p(
|
|
988
|
+
year: p(r2.year),
|
|
989
|
+
month: p(r2.month),
|
|
990
|
+
day: p(r2.day)
|
|
973
991
|
};
|
|
974
992
|
}
|
|
975
|
-
function c(
|
|
976
|
-
return new Date(
|
|
993
|
+
function c(r2, t2) {
|
|
994
|
+
return new Date(r2 || 2001, t2 || 1, 0).getDate();
|
|
977
995
|
}
|
|
978
|
-
function b(
|
|
979
|
-
const { year: t2, month: i, day: s } = f(
|
|
996
|
+
function b(r2) {
|
|
997
|
+
const { year: t2, month: i, day: s } = f(r2);
|
|
980
998
|
if (!t2 || t2 < 0 || t2 > 9999 || !i || i < 1 || i > 12 || !s || s < 1)
|
|
981
999
|
return;
|
|
982
1000
|
const n = new Date(Date.UTC(t2, i - 1, s));
|
|
983
1001
|
if (!(n.getUTCFullYear() !== t2 || n.getUTCMonth() !== i - 1 || n.getUTCDate() !== s))
|
|
984
1002
|
return { year: t2, month: i, day: s };
|
|
985
1003
|
}
|
|
986
|
-
function C(
|
|
987
|
-
const t2 = b(
|
|
1004
|
+
function C(r2) {
|
|
1005
|
+
const t2 = b(r2);
|
|
988
1006
|
return t2 ? new Date(Date.UTC(t2.year, t2.month - 1, t2.day)) : undefined;
|
|
989
1007
|
}
|
|
990
|
-
function T2(
|
|
1008
|
+
function T2(r2, t2, i, s) {
|
|
991
1009
|
const n = i ? {
|
|
992
1010
|
year: i.getUTCFullYear(),
|
|
993
1011
|
month: i.getUTCMonth() + 1,
|
|
@@ -997,7 +1015,7 @@ function T2(r, t2, i, s) {
|
|
|
997
1015
|
month: s.getUTCMonth() + 1,
|
|
998
1016
|
day: s.getUTCDate()
|
|
999
1017
|
} : null;
|
|
1000
|
-
return
|
|
1018
|
+
return r2 === "year" ? { min: n?.year ?? 1, max: e?.year ?? 9999 } : r2 === "month" ? {
|
|
1001
1019
|
min: n && t2.year === n.year ? n.month : 1,
|
|
1002
1020
|
max: e && t2.year === e.year ? e.month : 12
|
|
1003
1021
|
} : {
|
|
@@ -1170,26 +1188,26 @@ var u$1 = class u extends V {
|
|
|
1170
1188
|
cursor = 0;
|
|
1171
1189
|
#t;
|
|
1172
1190
|
getGroupItems(t2) {
|
|
1173
|
-
return this.options.filter((
|
|
1191
|
+
return this.options.filter((r2) => r2.group === t2);
|
|
1174
1192
|
}
|
|
1175
1193
|
isGroupSelected(t2) {
|
|
1176
|
-
const
|
|
1177
|
-
return e === undefined ? false :
|
|
1194
|
+
const r2 = this.getGroupItems(t2), e = this.value;
|
|
1195
|
+
return e === undefined ? false : r2.every((s) => e.includes(s.value));
|
|
1178
1196
|
}
|
|
1179
1197
|
toggleValue() {
|
|
1180
1198
|
const t2 = this.options[this.cursor];
|
|
1181
1199
|
if (this.value === undefined && (this.value = []), t2.group === true) {
|
|
1182
|
-
const
|
|
1183
|
-
this.isGroupSelected(
|
|
1200
|
+
const r2 = t2.value, e = this.getGroupItems(r2);
|
|
1201
|
+
this.isGroupSelected(r2) ? 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));
|
|
1184
1202
|
} else {
|
|
1185
|
-
const
|
|
1186
|
-
this.value =
|
|
1203
|
+
const r2 = this.value.includes(t2.value);
|
|
1204
|
+
this.value = r2 ? this.value.filter((e) => e !== t2.value) : [...this.value, t2.value];
|
|
1187
1205
|
}
|
|
1188
1206
|
}
|
|
1189
1207
|
constructor(t2) {
|
|
1190
1208
|
super(t2, false);
|
|
1191
|
-
const { options:
|
|
1192
|
-
this.#t = t2.selectableGroups !== false, this.options = Object.entries(
|
|
1209
|
+
const { options: r2 } = t2;
|
|
1210
|
+
this.#t = t2.selectableGroups !== false, this.options = Object.entries(r2).flatMap(([e, s]) => [
|
|
1193
1211
|
{ value: e, group: true, label: e },
|
|
1194
1212
|
...s.map((i) => ({ ...i, group: e }))
|
|
1195
1213
|
]), this.value = [...t2.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === t2.cursorAt), this.#t ? 0 : 1), this.on("cursor", (e) => {
|
|
@@ -1227,10 +1245,10 @@ class h extends V {
|
|
|
1227
1245
|
const t2 = this.userInput;
|
|
1228
1246
|
if (this.cursor >= t2.length)
|
|
1229
1247
|
return `${t2}█`;
|
|
1230
|
-
const s = t2.slice(0, this.cursor),
|
|
1231
|
-
return
|
|
1248
|
+
const s = t2.slice(0, this.cursor), r2 = t2[this.cursor], i = t2.slice(this.cursor + 1);
|
|
1249
|
+
return r2 === `
|
|
1232
1250
|
` ? `${s}█
|
|
1233
|
-
${i}` : `${s}${styleText("inverse",
|
|
1251
|
+
${i}` : `${s}${styleText("inverse", r2)}${i}`;
|
|
1234
1252
|
}
|
|
1235
1253
|
get cursor() {
|
|
1236
1254
|
return this._cursor;
|
|
@@ -1263,8 +1281,8 @@ ${i}` : `${s}${styleText("inverse", r)}${i}`;
|
|
|
1263
1281
|
if (this.#s)
|
|
1264
1282
|
return this.focused === "submit" ? true : (this.#r(`
|
|
1265
1283
|
`), this._cursor++, false);
|
|
1266
|
-
const
|
|
1267
|
-
return this.#t = true,
|
|
1284
|
+
const r2 = this.#t;
|
|
1285
|
+
return this.#t = true, r2 && this.cursor === this.userInput.length ? (this.userInput[this.cursor - 1] === `
|
|
1268
1286
|
` && (this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--), true) : (this.#r(`
|
|
1269
1287
|
`), this._cursor++, false);
|
|
1270
1288
|
}
|
|
@@ -1273,12 +1291,12 @@ ${i}` : `${s}${styleText("inverse", r)}${i}`;
|
|
|
1273
1291
|
super({
|
|
1274
1292
|
...t2,
|
|
1275
1293
|
initialUserInput: s
|
|
1276
|
-
}, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (
|
|
1294
|
+
}, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (r2, i) => {
|
|
1277
1295
|
if (i?.name && o$1.has(i.name)) {
|
|
1278
1296
|
this.#t = false, this.#i(i.name);
|
|
1279
1297
|
return;
|
|
1280
1298
|
}
|
|
1281
|
-
if (
|
|
1299
|
+
if (r2 === "\t" && this.#s) {
|
|
1282
1300
|
this.focused = this.focused === "editor" ? "submit" : "editor";
|
|
1283
1301
|
return;
|
|
1284
1302
|
}
|
|
@@ -1291,10 +1309,10 @@ ${i}` : `${s}${styleText("inverse", r)}${i}`;
|
|
|
1291
1309
|
this._setUserInput(this.userInput.slice(0, this.cursor) + this.userInput.slice(this.cursor + 1));
|
|
1292
1310
|
return;
|
|
1293
1311
|
}
|
|
1294
|
-
|
|
1312
|
+
r2 && (this.#s && this.focused === "submit" && (this.focused = "editor"), this.#r(r2 ?? ""), this._cursor++);
|
|
1295
1313
|
}
|
|
1296
|
-
}), this.on("userInput", (
|
|
1297
|
-
this._setValue(
|
|
1314
|
+
}), this.on("userInput", (r2) => {
|
|
1315
|
+
this._setValue(r2);
|
|
1298
1316
|
}), this.on("finalize", () => {
|
|
1299
1317
|
this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
|
|
1300
1318
|
});
|
|
@@ -1334,8 +1352,8 @@ class n extends V {
|
|
|
1334
1352
|
const t2 = this.userInput;
|
|
1335
1353
|
if (this.cursor >= t2.length)
|
|
1336
1354
|
return `${this.userInput}█`;
|
|
1337
|
-
const e = t2.slice(0, this.cursor), [s, ...
|
|
1338
|
-
return `${e}${styleText("inverse", s)}${
|
|
1355
|
+
const e = t2.slice(0, this.cursor), [s, ...r2] = t2.slice(this.cursor);
|
|
1356
|
+
return `${e}${styleText("inverse", s)}${r2.join("")}`;
|
|
1339
1357
|
}
|
|
1340
1358
|
get cursor() {
|
|
1341
1359
|
return this._cursor;
|
|
@@ -1469,6 +1487,41 @@ var limitOptions = ({
|
|
|
1469
1487
|
b2.push(n2);
|
|
1470
1488
|
return u3 && b2.push(C2), b2;
|
|
1471
1489
|
};
|
|
1490
|
+
var confirm = (i) => {
|
|
1491
|
+
const a2 = i.active ?? "Yes", s = i.inactive ?? "No";
|
|
1492
|
+
return new r({
|
|
1493
|
+
active: a2,
|
|
1494
|
+
inactive: s,
|
|
1495
|
+
signal: i.signal,
|
|
1496
|
+
input: i.input,
|
|
1497
|
+
output: i.output,
|
|
1498
|
+
initialValue: i.initialValue ?? true,
|
|
1499
|
+
render() {
|
|
1500
|
+
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)}
|
|
1501
|
+
` : ""}${f2}
|
|
1502
|
+
`, c2 = this.value ? a2 : s;
|
|
1503
|
+
switch (this.state) {
|
|
1504
|
+
case "submit": {
|
|
1505
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
1506
|
+
return `${o2}${r2}${styleText2("dim", c2)}`;
|
|
1507
|
+
}
|
|
1508
|
+
case "cancel": {
|
|
1509
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
1510
|
+
return `${o2}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
|
|
1511
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1512
|
+
}
|
|
1513
|
+
default: {
|
|
1514
|
+
const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e ? styleText2("cyan", S_BAR_END) : "";
|
|
1515
|
+
return `${o2}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i.vertical ? e ? `
|
|
1516
|
+
${styleText2("cyan", S_BAR)} ` : `
|
|
1517
|
+
` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
|
|
1518
|
+
${g2}
|
|
1519
|
+
`;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}).prompt();
|
|
1524
|
+
};
|
|
1472
1525
|
var MULTISELECT_INSTRUCTIONS = [
|
|
1473
1526
|
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
1474
1527
|
`${styleText2("dim", "Space:")} select`,
|
|
@@ -1904,10 +1957,24 @@ async function runOnboarding() {
|
|
|
1904
1957
|
console.clear();
|
|
1905
1958
|
console.log(import_picocolors.default.cyan(ASCII_LOGO));
|
|
1906
1959
|
intro(import_picocolors.default.inverse(" outlier: Welcome "));
|
|
1960
|
+
note(`Outlier is a local-first Policy Engine & Governance Framework for AI Engineering.
|
|
1961
|
+
|
|
1962
|
+
As agents write more of our code, we lose visibility into:
|
|
1963
|
+
1. Deskilling Risk (Are we becoming spectators in our own codebase?)
|
|
1964
|
+
2. Carbon Cost (What is the true regional energy cost of token caching?)
|
|
1965
|
+
3. Capability Drift (What hidden skills are our agents using?)`, "The Problem: AI Safety in Development");
|
|
1907
1966
|
note(`Outlier operates entirely on your machine.
|
|
1908
1967
|
- Local Only: No API keys. No cloud telemetry. No data leaves your machine.
|
|
1909
1968
|
- Native Auditing: We read your local \`~/.claude\` logs and \`.git/\` commit history.
|
|
1910
1969
|
- Actionable Policies: Enforce rules locally via terminal or Git hooks.`, "Privacy & Zero-Trust Principles");
|
|
1970
|
+
const ready = await confirm({
|
|
1971
|
+
message: "Are you ready to run your first Governance Audit and generate your Thermal Receipt?",
|
|
1972
|
+
initialValue: true
|
|
1973
|
+
});
|
|
1974
|
+
if (isCancel(ready) || !ready) {
|
|
1975
|
+
cancel("Onboarding paused. Run outlier again when you are ready.");
|
|
1976
|
+
process.exit(0);
|
|
1977
|
+
}
|
|
1911
1978
|
const configPath = join3(os.homedir(), ".outlier_config");
|
|
1912
1979
|
writeFileSync(configPath, JSON.stringify({ onboarded: true, date: new Date().toISOString() }));
|
|
1913
1980
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rosh100yx/outlier",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.16",
|
|
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/cli.ts
CHANGED
|
@@ -24,6 +24,16 @@ async function runOnboarding() {
|
|
|
24
24
|
console.log(pc.cyan(ASCII_LOGO));
|
|
25
25
|
intro(pc.inverse(' outlier: Welcome '));
|
|
26
26
|
|
|
27
|
+
note(
|
|
28
|
+
`Outlier is a local-first Policy Engine & Governance Framework for AI Engineering.
|
|
29
|
+
|
|
30
|
+
As agents write more of our code, we lose visibility into:
|
|
31
|
+
1. Deskilling Risk (Are we becoming spectators in our own codebase?)
|
|
32
|
+
2. Carbon Cost (What is the true regional energy cost of token caching?)
|
|
33
|
+
3. Capability Drift (What hidden skills are our agents using?)`,
|
|
34
|
+
'The Problem: AI Safety in Development'
|
|
35
|
+
);
|
|
36
|
+
|
|
27
37
|
note(
|
|
28
38
|
`Outlier operates entirely on your machine.
|
|
29
39
|
- Local Only: No API keys. No cloud telemetry. No data leaves your machine.
|
|
@@ -32,6 +42,16 @@ async function runOnboarding() {
|
|
|
32
42
|
'Privacy & Zero-Trust Principles'
|
|
33
43
|
);
|
|
34
44
|
|
|
45
|
+
const ready = await confirm({
|
|
46
|
+
message: 'Are you ready to run your first Governance Audit and generate your Thermal Receipt?',
|
|
47
|
+
initialValue: true,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (isCancel(ready) || !ready) {
|
|
51
|
+
cancel('Onboarding paused. Run outlier again when you are ready.');
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
35
55
|
const configPath = join(os.homedir(), '.outlier_config');
|
|
36
56
|
writeFileSync(configPath, JSON.stringify({ onboarded: true, date: new Date().toISOString() }));
|
|
37
57
|
}
|