@rosh100yx/outlier 0.4.15 → 0.4.18
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 +27 -29
- package/bin/outlier.js +117 -50
- package/package.json +11 -11
- package/src/cli.ts +20 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/rosh100yx/outlier/main/assets/cover.jpg" alt="Outlier
|
|
3
|
-
<h1>
|
|
4
|
-
<p><b>
|
|
5
|
-
<p><i>
|
|
2
|
+
<img src="https://raw.githubusercontent.com/rosh100yx/outlier/main/assets/cover.jpg" alt="Outlier: AI Code Governance and Policy Engine" width="100%" />
|
|
3
|
+
<h1>Outlier: The Governance & Policy Engine for AI Engineering</h1>
|
|
4
|
+
<p><b>Measure AI adoption. Enforce Zero-Trust. Protect Human Mastery.</b></p>
|
|
5
|
+
<p><i>Outlier is an open-source, local-first CLI tool that measures AI code reliance, enforces zero-trust telemetry, and protects developers from deskilling by auditing local agent logs (Claude, Cursor) and Git history.</i></p>
|
|
6
6
|
<br/>
|
|
7
7
|
|
|
8
8
|
<p>
|
|
@@ -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
|
|
@@ -106,13 +104,13 @@ If you run `outlier` directly, you'll be greeted with our frictionless UX:
|
|
|
106
104
|
```bash
|
|
107
105
|
git commit -am "added massive ai feature"
|
|
108
106
|
```
|
|
109
|
-
*Watch the Bouncer block your commit for deskilling risk.*
|
|
107
|
+
*Watch the Bouncer physically block your commit for deskilling risk.*
|
|
110
108
|
|
|
111
109
|
3. **Measure the Damage**
|
|
112
110
|
```bash
|
|
113
|
-
npx @rosh100yx/outlier
|
|
111
|
+
npx @rosh100yx/outlier
|
|
114
112
|
```
|
|
115
|
-
*
|
|
113
|
+
*Instantly generate your Thermal Receipt to see your exact AI Authorship ratio and Token Waste.*
|
|
116
114
|
|
|
117
115
|
## Theoretical Foundations
|
|
118
116
|
`outlier` is the live, technical implementation of an academic thesis on the thermodynamics of AI code generation and digital sovereignty.
|
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.18",
|
|
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"
|
|
@@ -180,7 +180,8 @@ var require_package = __commonJS((exports, module) => {
|
|
|
180
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
|
-
postinstall: "node bin/postinstall.js"
|
|
183
|
+
postinstall: "node bin/postinstall.js",
|
|
184
|
+
prepublishOnly: "npm run build"
|
|
184
185
|
},
|
|
185
186
|
type: "module",
|
|
186
187
|
private: false,
|
|
@@ -191,17 +192,16 @@ var require_package = __commonJS((exports, module) => {
|
|
|
191
192
|
url: "https://github.com/rosh100yx/outlier.git"
|
|
192
193
|
},
|
|
193
194
|
keywords: [
|
|
194
|
-
"ai",
|
|
195
|
-
"governance",
|
|
196
|
-
"carbon",
|
|
197
|
-
"compliance",
|
|
195
|
+
"ai-governance",
|
|
198
196
|
"ai-safety",
|
|
199
|
-
"
|
|
200
|
-
"
|
|
201
|
-
"
|
|
202
|
-
"
|
|
203
|
-
"
|
|
197
|
+
"deskilling",
|
|
198
|
+
"claude-code",
|
|
199
|
+
"cursor",
|
|
200
|
+
"git-hook",
|
|
201
|
+
"pre-commit",
|
|
204
202
|
"telemetry",
|
|
203
|
+
"carbon-footprint",
|
|
204
|
+
"zero-trust",
|
|
205
205
|
"authorship",
|
|
206
206
|
"cli"
|
|
207
207
|
],
|
|
@@ -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.18",
|
|
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"
|
|
@@ -15,7 +15,8 @@
|
|
|
15
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
|
-
"postinstall": "node bin/postinstall.js"
|
|
18
|
+
"postinstall": "node bin/postinstall.js",
|
|
19
|
+
"prepublishOnly": "npm run build"
|
|
19
20
|
},
|
|
20
21
|
"type": "module",
|
|
21
22
|
"private": false,
|
|
@@ -26,17 +27,16 @@
|
|
|
26
27
|
"url": "https://github.com/rosh100yx/outlier.git"
|
|
27
28
|
},
|
|
28
29
|
"keywords": [
|
|
29
|
-
"ai",
|
|
30
|
-
"governance",
|
|
31
|
-
"carbon",
|
|
32
|
-
"compliance",
|
|
30
|
+
"ai-governance",
|
|
33
31
|
"ai-safety",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
32
|
+
"deskilling",
|
|
33
|
+
"claude-code",
|
|
34
|
+
"cursor",
|
|
35
|
+
"git-hook",
|
|
36
|
+
"pre-commit",
|
|
39
37
|
"telemetry",
|
|
38
|
+
"carbon-footprint",
|
|
39
|
+
"zero-trust",
|
|
40
40
|
"authorship",
|
|
41
41
|
"cli"
|
|
42
42
|
],
|
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
|
}
|