@rosh100yx/outlier 0.2.2 → 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 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
- ## Contributing
109
- We welcome contributions! 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.
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rosh100yx/outlier",
3
- "version": "0.2.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
6
  "outlier": "bin/outlier.js"
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
- const logFile = file(logPath);
28
- if (!(await logFile.exists())) return { total: 0, output: 0, cache: 0, sessions: 0 };
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 logFile.text();
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
- outro(pc.green('Local telemetry run completed. No data left your machine.'));
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 { spawn } from 'bun';
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
- async function runGitCommand(args: string[], cwd: string): Promise<number> {
13
- const proc = spawn(['git', '-C', cwd, ...args], { stdout: 'pipe', stderr: 'pipe' });
14
- const text = await new Response(proc.stdout).text();
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 = spawn(['git', '-C', cwd, 'rev-parse', '--is-inside-work-tree'], { stdout: 'pipe', stderr: 'pipe' });
27
- const exitCode = await proc.exited;
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 = await runGitCommand(['log', '--oneline'], repoPath);
38
- const ai = await runGitCommand(['log', '-i', '--grep=Co-Authored-By', '--oneline'], repoPath);
39
- const totalNoMerges = await runGitCommand(['log', '--no-merges', '--oneline'], repoPath);
40
- const aiNoMerges = await runGitCommand(['log', '--no-merges', '-i', '--grep=Co-Authored-By', '--oneline'], repoPath);
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,