@rosh100yx/outlier 0.2.1 → 0.2.3
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 +6 -2
- package/bin/outlier.js +14 -2
- package/package.json +2 -2
- package/src/carbon.ts +8 -4
- package/src/cli.ts +6 -1
- package/src/git.ts +11 -15
package/README.md
CHANGED
|
@@ -105,8 +105,12 @@ If you hold one of these roles, `outlier` was built specifically for you. Please
|
|
|
105
105
|
- **Principal & Staff Engineers:** Protect the craft. Use the Bouncer hook to enforce architectural standards and prevent your team from deskilling.
|
|
106
106
|
- **Developers & "Vibe Coders":** Prove your mastery. Run the audit, check your vibe, and post your "Artisan" or "Centaur" terminal status to the community.
|
|
107
107
|
|
|
108
|
-
##
|
|
109
|
-
|
|
108
|
+
## Support the Thesis & Collaborate
|
|
109
|
+
This tool is the technical implementation of an ongoing academic thesis on the thermodynamics of AI code generation, skill atrophy, and digital sovereignty. We are actively looking for collaborators, researchers, and engineers to expand this framework.
|
|
110
|
+
|
|
111
|
+
**Call for Research Data:** If you use this tool, please consider sharing your terminal screenshot (`outlier audit`) on X.com or with the maintainers. By voluntarily sharing your baseline AI reliance and cache bloat metrics, you help us build a broader empirical dataset on how AI is impacting global engineering teams.
|
|
112
|
+
|
|
113
|
+
See our [Contributing Guide](CONTRIBUTING.md) to get started. Great first issues include adding new regional grid factors to `data/grid-factors.json` or writing custom CI/CD pipeline integrations.
|
|
110
114
|
|
|
111
115
|
## License
|
|
112
116
|
Apache 2.0
|
package/bin/outlier.js
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
import
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'child_process';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
const cliPath = path.join(__dirname, '../src/cli.ts');
|
|
10
|
+
const result = spawnSync('bun', ['run', cliPath, ...process.argv.slice(2)], {
|
|
11
|
+
stdio: 'inherit'
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
process.exit(result.status || 0);
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rosh100yx/outlier",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
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
|
-
"outlier": "
|
|
6
|
+
"outlier": "bin/outlier.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"bin",
|
package/src/carbon.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { file } from 'bun';
|
|
2
1
|
import { homedir } from 'os';
|
|
3
2
|
import { join } from 'path';
|
|
3
|
+
import { readFile, access } from 'fs/promises';
|
|
4
4
|
import gridFactors from '../data/grid-factors.json';
|
|
5
5
|
|
|
6
6
|
export interface CarbonStats {
|
|
@@ -24,10 +24,14 @@ export class ClaudeLogParser implements TokenLogParser {
|
|
|
24
24
|
}
|
|
25
25
|
async parse() {
|
|
26
26
|
const logPath = join(this.baseDir, '.claude', 'tokenomics-log.jsonl');
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await access(logPath);
|
|
30
|
+
} catch {
|
|
31
|
+
return { total: 0, output: 0, cache: 0, sessions: 0 };
|
|
32
|
+
}
|
|
29
33
|
|
|
30
|
-
const text = await
|
|
34
|
+
const text = await readFile(logPath, 'utf-8');
|
|
31
35
|
const lines = text.trim().split('\n').filter(l => l.length > 0);
|
|
32
36
|
|
|
33
37
|
let total = 0, output = 0, cache = 0;
|
package/src/cli.ts
CHANGED
|
@@ -270,7 +270,12 @@ Artifact: ${pc.cyan('outlier-audit-report.jsonl generated')}`,
|
|
|
270
270
|
);
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
|
|
273
|
+
let shareText = 'Local telemetry run completed. No data left your machine.';
|
|
274
|
+
if (action === 'status') {
|
|
275
|
+
shareText += `\n\n${pc.dim('└')} ${pc.cyan('Share your audit:')} https://x.com/intent/tweet?text=I%20just%20audited%20my%20codebase%20for%20AI%20reliance%20and%20deskilling%20risk.%20What%20does%20your%20repo%20score%3F%0A%0A%F0%9F%93%8F%20npx%20%40rosh100yx%2Foutlier`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
outro(shareText);
|
|
274
279
|
}
|
|
275
280
|
|
|
276
281
|
main().catch(console.error);
|
package/src/git.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
2
|
|
|
3
3
|
export interface AuthorshipStats {
|
|
4
4
|
total: number;
|
|
@@ -9,23 +9,19 @@ export interface AuthorshipStats {
|
|
|
9
9
|
ratioNoMerges: number;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
const proc =
|
|
14
|
-
|
|
15
|
-
const exitCode = await proc.exited;
|
|
16
|
-
|
|
17
|
-
if (exitCode !== 0) {
|
|
12
|
+
function runGitCommand(args: string[], cwd: string): number {
|
|
13
|
+
const proc = spawnSync('git', ['-C', cwd, ...args], { encoding: 'utf-8' });
|
|
14
|
+
if (proc.status !== 0) {
|
|
18
15
|
throw new Error('Git command failed');
|
|
19
16
|
}
|
|
20
|
-
|
|
17
|
+
const text = proc.stdout || '';
|
|
21
18
|
const lines = text.trim().split('\n').filter(l => l.length > 0);
|
|
22
19
|
return lines.length;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
export async function checkIsGitRepo(cwd: string): Promise<boolean> {
|
|
26
|
-
const proc =
|
|
27
|
-
|
|
28
|
-
return exitCode === 0;
|
|
23
|
+
const proc = spawnSync('git', ['-C', cwd, 'rev-parse', '--is-inside-work-tree'], { encoding: 'utf-8' });
|
|
24
|
+
return proc.status === 0;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
export async function getAuthorshipStats(repoPath: string = process.cwd()): Promise<AuthorshipStats> {
|
|
@@ -34,10 +30,10 @@ export async function getAuthorshipStats(repoPath: string = process.cwd()): Prom
|
|
|
34
30
|
throw new Error(`Directory is not a git repository: ${repoPath}`);
|
|
35
31
|
}
|
|
36
32
|
|
|
37
|
-
const total =
|
|
38
|
-
const ai =
|
|
39
|
-
const totalNoMerges =
|
|
40
|
-
const aiNoMerges =
|
|
33
|
+
const total = runGitCommand(['log', '--oneline'], repoPath);
|
|
34
|
+
const ai = runGitCommand(['log', '-i', '--grep=Co-Authored-By', '--oneline'], repoPath);
|
|
35
|
+
const totalNoMerges = runGitCommand(['log', '--no-merges', '--oneline'], repoPath);
|
|
36
|
+
const aiNoMerges = runGitCommand(['log', '--no-merges', '-i', '--grep=Co-Authored-By', '--oneline'], repoPath);
|
|
41
37
|
|
|
42
38
|
return {
|
|
43
39
|
total,
|