fivocell 1.0.5 → 3.0.0
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 +63 -464
- package/bin/cell.js +2 -2
- package/dist/behavior-intelligence.d.ts +90 -0
- package/dist/behavior-intelligence.d.ts.map +1 -0
- package/dist/behavior-intelligence.js +595 -0
- package/dist/behavior-intelligence.js.map +1 -0
- package/dist/behavioral-tracker.d.ts +90 -0
- package/dist/behavioral-tracker.d.ts.map +1 -0
- package/dist/behavioral-tracker.js +185 -0
- package/dist/behavioral-tracker.js.map +1 -0
- package/dist/cli.js +417 -1659
- package/dist/cli.js.map +1 -1
- package/dist/cloud-sync.d.ts +66 -0
- package/dist/cloud-sync.d.ts.map +1 -0
- package/dist/cloud-sync.js +328 -0
- package/dist/cloud-sync.js.map +1 -0
- package/dist/code-scanner.d.ts +51 -0
- package/dist/code-scanner.d.ts.map +1 -0
- package/dist/code-scanner.js +966 -0
- package/dist/code-scanner.js.map +1 -0
- package/dist/community-intel.d.ts +34 -0
- package/dist/community-intel.d.ts.map +1 -0
- package/dist/community-intel.js +148 -0
- package/dist/community-intel.js.map +1 -0
- package/dist/community-intelligence.d.ts +42 -0
- package/dist/community-intelligence.d.ts.map +1 -0
- package/dist/community-intelligence.js +160 -0
- package/dist/community-intelligence.js.map +1 -0
- package/dist/community-v2.d.ts +106 -0
- package/dist/community-v2.d.ts.map +1 -0
- package/dist/community-v2.js +378 -0
- package/dist/community-v2.js.map +1 -0
- package/dist/core/__tests__/chapter8-hostile.test.js +1 -1
- package/dist/core/__tests__/chapter8-hostile.test.js.map +1 -1
- package/dist/core/__tests__/chapter9-hostile.test.js +1 -1
- package/dist/core/__tests__/chapter9-hostile.test.js.map +1 -1
- package/dist/core/__tests__/complexity-analyzer.test.js +15 -15
- package/dist/core/__tests__/team-composer.test.js +2 -1
- package/dist/core/__tests__/team-composer.test.js.map +1 -1
- package/dist/core/convention-detector.d.ts.map +1 -1
- package/dist/core/convention-detector.js +11 -23
- package/dist/core/convention-detector.js.map +1 -1
- package/dist/core/cost-optimizer.d.ts.map +1 -1
- package/dist/core/cost-optimizer.js +13 -25
- package/dist/core/cost-optimizer.js.map +1 -1
- package/dist/core/database.d.ts +28 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +587 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/knowledge-graph.d.ts.map +1 -1
- package/dist/core/knowledge-graph.js +9 -24
- package/dist/core/knowledge-graph.js.map +1 -1
- package/dist/core/logger.d.ts +9 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +26 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/playbook-generator.js +48 -48
- package/dist/core/privacy-manager.d.ts.map +1 -1
- package/dist/core/privacy-manager.js +5 -0
- package/dist/core/privacy-manager.js.map +1 -1
- package/dist/core/project-dna.d.ts.map +1 -1
- package/dist/core/project-dna.js +6 -19
- package/dist/core/project-dna.js.map +1 -1
- package/dist/core/prompt-builder.d.ts +18 -0
- package/dist/core/prompt-builder.d.ts.map +1 -0
- package/dist/core/prompt-builder.js +325 -0
- package/dist/core/prompt-builder.js.map +1 -0
- package/dist/core/session-memory.d.ts +90 -0
- package/dist/core/session-memory.d.ts.map +1 -0
- package/dist/core/session-memory.js +229 -0
- package/dist/core/session-memory.js.map +1 -0
- package/dist/core/signal-capture.d.ts +5 -0
- package/dist/core/signal-capture.d.ts.map +1 -1
- package/dist/core/signal-capture.js +67 -0
- package/dist/core/signal-capture.js.map +1 -1
- package/dist/core/team-composer.d.ts.map +1 -1
- package/dist/core/team-composer.js +16 -6
- package/dist/core/team-composer.js.map +1 -1
- package/dist/cross-model-memory.d.ts +95 -0
- package/dist/cross-model-memory.d.ts.map +1 -0
- package/dist/cross-model-memory.js +229 -0
- package/dist/cross-model-memory.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +3 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +98 -64
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +637 -25
- package/dist/daemon/server.js.map +1 -1
- package/dist/developer-intelligence.d.ts +18 -0
- package/dist/developer-intelligence.d.ts.map +1 -0
- package/dist/developer-intelligence.js +180 -0
- package/dist/developer-intelligence.js.map +1 -0
- package/dist/first-run.d.ts +8 -0
- package/dist/first-run.d.ts.map +1 -0
- package/dist/first-run.js +182 -0
- package/dist/first-run.js.map +1 -0
- package/dist/focus-report.d.ts +32 -0
- package/dist/focus-report.d.ts.map +1 -0
- package/dist/focus-report.js +293 -0
- package/dist/focus-report.js.map +1 -0
- package/dist/ide-intelligence.d.ts +118 -0
- package/dist/ide-intelligence.d.ts.map +1 -0
- package/dist/ide-intelligence.js +284 -0
- package/dist/ide-intelligence.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +119 -2
- package/dist/index.js.map +1 -1
- package/dist/insight-generator.d.ts +58 -0
- package/dist/insight-generator.d.ts.map +1 -0
- package/dist/insight-generator.js +314 -0
- package/dist/insight-generator.js.map +1 -0
- package/dist/journey-memory.d.ts +75 -0
- package/dist/journey-memory.d.ts.map +1 -0
- package/dist/journey-memory.js +360 -0
- package/dist/journey-memory.js.map +1 -0
- package/dist/layers.d.ts +92 -0
- package/dist/layers.d.ts.map +1 -0
- package/dist/layers.js +226 -0
- package/dist/layers.js.map +1 -0
- package/dist/mcp-server.d.ts +406 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +414 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/onboarding-scan.d.ts +174 -0
- package/dist/onboarding-scan.d.ts.map +1 -0
- package/dist/onboarding-scan.js +1039 -0
- package/dist/onboarding-scan.js.map +1 -0
- package/dist/pc-scanner.d.ts +46 -0
- package/dist/pc-scanner.d.ts.map +1 -0
- package/dist/pc-scanner.js +488 -0
- package/dist/pc-scanner.js.map +1 -0
- package/dist/personal-intelligence.d.ts +97 -0
- package/dist/personal-intelligence.d.ts.map +1 -0
- package/dist/personal-intelligence.js +408 -0
- package/dist/personal-intelligence.js.map +1 -0
- package/dist/predictive-engine.d.ts +19 -0
- package/dist/predictive-engine.d.ts.map +1 -0
- package/dist/predictive-engine.js +107 -0
- package/dist/predictive-engine.js.map +1 -0
- package/dist/predictive-intelligence.d.ts +95 -0
- package/dist/predictive-intelligence.d.ts.map +1 -0
- package/dist/predictive-intelligence.js +544 -0
- package/dist/predictive-intelligence.js.map +1 -0
- package/dist/production.d.ts +67 -0
- package/dist/production.d.ts.map +1 -0
- package/dist/production.js +333 -0
- package/dist/production.js.map +1 -0
- package/dist/senior-features.d.ts +63 -0
- package/dist/senior-features.d.ts.map +1 -0
- package/dist/senior-features.js +325 -0
- package/dist/senior-features.js.map +1 -0
- package/dist/style-pull.d.ts +40 -0
- package/dist/style-pull.d.ts.map +1 -0
- package/dist/style-pull.js +385 -0
- package/dist/style-pull.js.map +1 -0
- package/dist/team-collaboration.d.ts +116 -0
- package/dist/team-collaboration.d.ts.map +1 -0
- package/dist/team-collaboration.js +375 -0
- package/dist/team-collaboration.js.map +1 -0
- package/dist/team-git.d.ts +47 -0
- package/dist/team-git.d.ts.map +1 -0
- package/dist/team-git.js +305 -0
- package/dist/team-git.js.map +1 -0
- package/dist/team-intelligence.d.ts +64 -0
- package/dist/team-intelligence.d.ts.map +1 -0
- package/dist/team-intelligence.js +289 -0
- package/dist/team-intelligence.js.map +1 -0
- package/dist/test-watch.d.ts +2 -0
- package/dist/test-watch.d.ts.map +1 -0
- package/dist/test-watch.js +8 -0
- package/dist/test-watch.js.map +1 -0
- package/dist/user-intelligence.d.ts +69 -0
- package/dist/user-intelligence.d.ts.map +1 -0
- package/dist/user-intelligence.js +553 -0
- package/dist/user-intelligence.js.map +1 -0
- package/dist/work-style.d.ts +49 -0
- package/dist/work-style.d.ts.map +1 -0
- package/dist/work-style.js +247 -0
- package/dist/work-style.js.map +1 -0
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -37,1764 +37,522 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
const commander_1 = require("commander");
|
|
41
40
|
const path = __importStar(require("path"));
|
|
42
41
|
const fs = __importStar(require("fs"));
|
|
43
|
-
const os = __importStar(require("os"));
|
|
44
42
|
const chalk_1 = __importDefault(require("chalk"));
|
|
45
43
|
const figlet_1 = __importDefault(require("figlet"));
|
|
46
44
|
const gradient_string_1 = __importDefault(require("gradient-string"));
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
45
|
+
const database_1 = require("./core/database");
|
|
46
|
+
const layers_1 = require("./layers");
|
|
47
|
+
(0, database_1.initializeDatabase)();
|
|
50
48
|
const C = {
|
|
51
49
|
primary: chalk_1.default.hex('#FF6B35'),
|
|
52
|
-
primaryLight: chalk_1.default.hex('#FF8C42'),
|
|
53
|
-
primaryDark: chalk_1.default.hex('#E65100'),
|
|
54
|
-
accent: chalk_1.default.hex('#FFAB91'),
|
|
55
50
|
success: chalk_1.default.green,
|
|
56
|
-
error: chalk_1.default.red,
|
|
57
51
|
warn: chalk_1.default.yellow,
|
|
58
|
-
info: chalk_1.default.hex('#FFAB91'),
|
|
59
52
|
dim: chalk_1.default.dim,
|
|
60
53
|
bold: chalk_1.default.bold,
|
|
61
54
|
num: (s) => chalk_1.default.hex('#FF6B35').bold(s),
|
|
62
|
-
header: (s) => chalk_1.default.hex('#FF8C42').bold(s),
|
|
63
|
-
sub: (s) => chalk_1.default.hex('#FFAB91').dim(s),
|
|
64
55
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
56
|
+
const project = path.basename(process.cwd());
|
|
57
|
+
// ─── Parse ──────────────────────────────────────────────────────────────────
|
|
58
|
+
const args = process.argv.slice(2);
|
|
59
|
+
const cmd = args[0] || '';
|
|
60
|
+
switch (cmd) {
|
|
61
|
+
case 'start':
|
|
62
|
+
doStart();
|
|
63
|
+
break;
|
|
64
|
+
case 'stop':
|
|
65
|
+
doStop();
|
|
66
|
+
break;
|
|
67
|
+
case 'scan':
|
|
68
|
+
doScan();
|
|
69
|
+
break;
|
|
70
|
+
case 'status':
|
|
71
|
+
doStatus();
|
|
72
|
+
break;
|
|
73
|
+
case 'team':
|
|
74
|
+
doTeam();
|
|
75
|
+
break;
|
|
76
|
+
case 'community':
|
|
77
|
+
doCommunity();
|
|
78
|
+
break;
|
|
79
|
+
case 'help':
|
|
80
|
+
doHelp();
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
doStatus();
|
|
84
|
+
break;
|
|
88
85
|
}
|
|
89
|
-
// ───
|
|
90
|
-
function
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
// ─── cell start ─────────────────────────────────────────────────────────────
|
|
87
|
+
function doStart() {
|
|
88
|
+
const banner = figlet_1.default.textSync('CELL', { font: 'ANSI Shadow', horizontalLayout: 'fitted' });
|
|
89
|
+
console.log((0, gradient_string_1.default)(['#FF6B35', '#FFAB91'])(banner));
|
|
90
|
+
console.log(C.dim(' Starting everything...\n'));
|
|
91
|
+
// 0. First-run greeting
|
|
95
92
|
try {
|
|
96
|
-
|
|
93
|
+
const { firstRunGreeting } = require('./first-run');
|
|
94
|
+
firstRunGreeting();
|
|
97
95
|
}
|
|
98
|
-
catch {
|
|
96
|
+
catch { }
|
|
97
|
+
// 1. Kill any stale daemon (clean restart)
|
|
98
|
+
try {
|
|
99
|
+
const { stopDaemon } = require('./daemon/lifecycle');
|
|
100
|
+
stopDaemon();
|
|
101
|
+
// Wait for port to be released
|
|
102
|
+
const { execSync } = require('child_process');
|
|
103
|
+
execSync('timeout /t 1 /nobreak >nul 2>&1', { stdio: 'ignore' });
|
|
104
|
+
}
|
|
105
|
+
catch { }
|
|
106
|
+
try {
|
|
107
|
+
const fsMod = require('fs');
|
|
108
|
+
const osMod = require('os');
|
|
109
|
+
const pidFile = require('path').join(osMod.homedir(), '.fivo', 'cell', 'daemon.pid');
|
|
99
110
|
try {
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
f = 'FIVO CELL';
|
|
111
|
+
fsMod.unlinkSync(pidFile);
|
|
104
112
|
}
|
|
113
|
+
catch { }
|
|
114
|
+
}
|
|
115
|
+
catch { }
|
|
116
|
+
// 2. Start daemon as detached background process
|
|
117
|
+
console.log(C.primary(' Starting daemon + MCP...'));
|
|
118
|
+
try {
|
|
119
|
+
const { spawn } = require('child_process');
|
|
120
|
+
const pathMod = require('path');
|
|
121
|
+
const fsMod = require('fs');
|
|
122
|
+
const osMod = require('os');
|
|
123
|
+
const serverPath = pathMod.join(__dirname, 'daemon', 'server.js');
|
|
124
|
+
const child = spawn('node', [serverPath], {
|
|
125
|
+
detached: true,
|
|
126
|
+
stdio: 'ignore',
|
|
127
|
+
});
|
|
128
|
+
child.unref();
|
|
129
|
+
// Write PID
|
|
130
|
+
const pidFile = pathMod.join(osMod.homedir(), '.fivo', 'cell', 'daemon.pid');
|
|
131
|
+
fsMod.mkdirSync(pathMod.dirname(pidFile), { recursive: true });
|
|
132
|
+
fsMod.writeFileSync(pidFile, String(child.pid), 'utf-8');
|
|
133
|
+
console.log(C.success(` Daemon + MCP started (PID: ${child.pid})`));
|
|
134
|
+
console.log(C.dim(' Daemon + MCP: http://localhost:9876'));
|
|
135
|
+
console.log(C.dim(' MCP endpoint: POST http://localhost:9876/mcp'));
|
|
136
|
+
console.log();
|
|
137
|
+
console.log(C.dim(' Next: cell scan (scan codebase + build layers)'));
|
|
138
|
+
console.log(C.dim(' Then: cell status'));
|
|
139
|
+
console.log();
|
|
140
|
+
process.exit(0);
|
|
105
141
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
console.log(thick);
|
|
110
|
-
console.log(C.primary.bold('\n ▸ Named Commands'));
|
|
111
|
-
console.log(line);
|
|
112
|
-
console.log(` ${C.primary.bold('run')} ${C.primary.bold('status')} ${C.primary.bold('start')} ${C.primary.bold('stop')}`);
|
|
113
|
-
console.log(C.primary.bold('\n ▸ Quick Commands'));
|
|
114
|
-
console.log(line);
|
|
115
|
-
const imp = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
116
|
-
for (let i = 0; i < imp.length; i += 5) {
|
|
117
|
-
const row = imp.slice(i, i + 5).map(n => `${C.num(String(n).padStart(2))} ${C.bold(NUM[n].padEnd(14))}`).join(C.dim(' │ '));
|
|
118
|
-
console.log(` ${row}`);
|
|
142
|
+
catch (e) {
|
|
143
|
+
console.log(C.warn(' Start failed: ' + String(e)));
|
|
144
|
+
process.exit(1);
|
|
119
145
|
}
|
|
120
|
-
console.log(C.primary.bold('\n ▸ Other Commands: 11-39'));
|
|
121
|
-
console.log(line);
|
|
122
|
-
console.log(C.dim(' cell 9 → Run command by number'));
|
|
123
|
-
console.log(C.dim(' cell 1,2,3 → Run multiple commands'));
|
|
124
|
-
console.log(C.dim(' cell 1-5 → Run range of commands'));
|
|
125
|
-
console.log();
|
|
126
|
-
console.log(thick);
|
|
127
|
-
console.log();
|
|
128
146
|
}
|
|
129
|
-
// ───
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
return [];
|
|
137
|
-
return Array.from({ length: e - s + 1 }, (_, i) => s + i);
|
|
147
|
+
// ─── cell stop ──────────────────────────────────────────────────────────────
|
|
148
|
+
function doStop() {
|
|
149
|
+
console.log(C.dim(' Stopping Cell daemon...'));
|
|
150
|
+
try {
|
|
151
|
+
const { stopDaemon } = require('./daemon/lifecycle');
|
|
152
|
+
const result = stopDaemon();
|
|
153
|
+
console.log(result.success ? C.success(` ${result.message}`) : C.warn(` ${result.message}`));
|
|
138
154
|
}
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
catch (e) {
|
|
156
|
+
console.log(C.warn(' Stop failed: ' + String(e)));
|
|
141
157
|
}
|
|
142
|
-
|
|
158
|
+
console.log();
|
|
143
159
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
console.log(C.
|
|
153
|
-
(0,
|
|
160
|
+
// ─── cell scan ───────────────────────────────────────────────────────────────
|
|
161
|
+
function doScan() {
|
|
162
|
+
const banner = figlet_1.default.textSync('CELL', { font: 'ANSI Shadow', horizontalLayout: 'fitted' });
|
|
163
|
+
console.log((0, gradient_string_1.default)(['#FF6B35', '#FFAB91'])(banner));
|
|
164
|
+
console.log(C.dim(' Scanning codebase + building all layers...\n'));
|
|
165
|
+
try {
|
|
166
|
+
const { scanCodebase } = require('./code-scanner');
|
|
167
|
+
const result = scanCodebase(process.cwd(), project);
|
|
168
|
+
console.log(C.success(` [1/2] Scanned ${result.filesScanned} files, ${result.totalLines.toLocaleString()} lines`));
|
|
169
|
+
(0, layers_1.populateAllLayers)({
|
|
170
|
+
profile: result.profile,
|
|
171
|
+
patterns: result.patterns,
|
|
172
|
+
project,
|
|
173
|
+
});
|
|
174
|
+
console.log(C.success(' [2/2] Populated all layers:'));
|
|
175
|
+
console.log(C.dim(' .cell/personal/ — profile, style, errors, decisions'));
|
|
176
|
+
console.log(C.dim(' .cell/team/ — shared patterns, blind spots'));
|
|
177
|
+
console.log(C.dim(' .cell/community/ — community patterns, trends'));
|
|
178
|
+
console.log();
|
|
179
|
+
console.log(C.dim(' Run: cell status'));
|
|
180
|
+
console.log();
|
|
154
181
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
program
|
|
159
|
-
.name('cell')
|
|
160
|
-
.description('FIVO Cell — Anticipatory Intelligence. Learns your coding taste.')
|
|
161
|
-
.version('1.0.0');
|
|
162
|
-
program
|
|
163
|
-
.command('run')
|
|
164
|
-
.description('Initialize FIVO Cell in the current project')
|
|
165
|
-
.action(() => {
|
|
166
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
167
|
-
if (!fs.existsSync(cellDir)) {
|
|
168
|
-
fs.mkdirSync(cellDir, { recursive: true });
|
|
182
|
+
catch (e) {
|
|
183
|
+
console.log(C.warn(' Scan failed: ' + String(e)));
|
|
184
|
+
console.log();
|
|
169
185
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
console.
|
|
175
|
-
console.log();
|
|
176
|
-
console.log(thick);
|
|
177
|
-
console.log(C.success.bold(centerText('✅ FIVO Cell Initialized')));
|
|
178
|
-
console.log(thick);
|
|
179
|
-
console.log();
|
|
180
|
-
console.log(C.info(' Directory: ') + C.bold(cellDir));
|
|
181
|
-
console.log(line);
|
|
182
|
-
console.log();
|
|
183
|
-
console.log(C.primary.bold(' 🌐 Cloud Sync: ON (Anonymous pattern stats only)'));
|
|
184
|
-
console.log(C.sub(' → Better suggestions from 10K+ developers'));
|
|
185
|
-
console.log(C.sub(' → Your code NEVER leaves your machine'));
|
|
186
|
-
console.log(C.sub(' → What we share (just stats, no code):'));
|
|
187
|
-
console.log(C.sub(' "prefers const over let (87%)"'));
|
|
188
|
-
console.log(C.sub(' "uses named exports, not default (83%)"'));
|
|
189
|
-
console.log(C.sub(' "vitest over jest (91%)"'));
|
|
190
|
-
console.log(C.sub(' "pnpm over npm (86%)"'));
|
|
191
|
-
console.log(C.sub(' → No file paths. No project names. No source code.'));
|
|
192
|
-
console.log(C.sub(' → Turn off anytime: cell cloud off'));
|
|
193
|
-
console.log();
|
|
194
|
-
console.log(line);
|
|
195
|
-
console.log(C.info(' Run ') + C.primary.bold('cell status') + C.info(' to see your taste profile.'));
|
|
196
|
-
console.log(C.dim(' Run ') + C.primary('cell watch') + C.dim(' for auto-learning from file edits'));
|
|
197
|
-
console.log(thick);
|
|
186
|
+
}
|
|
187
|
+
// ─── cell status ────────────────────────────────────────────────────────────
|
|
188
|
+
function doStatus() {
|
|
189
|
+
const banner = figlet_1.default.textSync('CELL', { font: 'ANSI Shadow', horizontalLayout: 'fitted' });
|
|
190
|
+
console.log((0, gradient_string_1.default)(['#FF6B35', '#FFAB91'])(banner));
|
|
198
191
|
console.log();
|
|
199
|
-
//
|
|
200
|
-
const
|
|
201
|
-
if (fs.existsSync(gitDir)) {
|
|
202
|
-
const hooksDir = path.join(gitDir, 'hooks');
|
|
203
|
-
if (!fs.existsSync(hooksDir))
|
|
204
|
-
fs.mkdirSync(hooksDir, { recursive: true });
|
|
205
|
-
const hookPath = path.join(hooksDir, 'post-commit');
|
|
206
|
-
if (!fs.existsSync(hookPath)) {
|
|
207
|
-
const cellBin = process.argv[1];
|
|
208
|
-
const hook = `#!/bin/sh
|
|
209
|
-
# FIVO Cell — auto-learn on commit
|
|
210
|
-
DIFF=$(git diff --cached --diff-algorithm=histogram)
|
|
211
|
-
if [ -n "$DIFF" ]; then
|
|
212
|
-
node "${cellBin}" learn --original "$(echo "$DIFF" | head -200)" --edited "committed" 2>/dev/null
|
|
213
|
-
fi
|
|
214
|
-
`;
|
|
215
|
-
fs.writeFileSync(hookPath, hook, { mode: 0o755 });
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
// Migration: legacy → .cell/ format
|
|
192
|
+
// Check daemon
|
|
193
|
+
const http = require('http');
|
|
219
194
|
try {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
195
|
+
http.get('http://localhost:9876/health', (res) => {
|
|
196
|
+
let data = '';
|
|
197
|
+
res.on('data', (c) => data += c);
|
|
198
|
+
res.on('end', () => {
|
|
199
|
+
console.log(C.success(' Daemon: Running'));
|
|
200
|
+
showProjectStatus();
|
|
201
|
+
});
|
|
202
|
+
}).on('error', () => {
|
|
203
|
+
console.log(C.warn(' Daemon: Not running (run: cell start)'));
|
|
204
|
+
showProjectStatus();
|
|
205
|
+
});
|
|
226
206
|
}
|
|
227
|
-
catch {
|
|
228
|
-
|
|
229
|
-
try {
|
|
230
|
-
const se = new index_1.SearchEngine();
|
|
231
|
-
const r = se.rebuild();
|
|
232
|
-
if (r.indexed > 0)
|
|
233
|
-
console.log(C.dim(` 🔍 Search index: ${r.indexed} files indexed`));
|
|
207
|
+
catch {
|
|
208
|
+
showProjectStatus();
|
|
234
209
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (!fs.existsSync(cellDir)) {
|
|
243
|
-
console.log('❌ Cell not initialized. Run `cell init` first.');
|
|
210
|
+
}
|
|
211
|
+
function showProjectStatus() {
|
|
212
|
+
const { getDeveloperProfile } = require('./code-scanner');
|
|
213
|
+
const profile = getDeveloperProfile(project);
|
|
214
|
+
if (!profile) {
|
|
215
|
+
console.log(C.warn(`\n No profile for "${project}". Run: cell start`));
|
|
216
|
+
console.log();
|
|
244
217
|
return;
|
|
245
218
|
}
|
|
246
|
-
const store = new index_1.PatternStore(cellDir);
|
|
247
|
-
const thick = C.primary(hline('━'));
|
|
248
|
-
const line = C.primaryDark(hline('─'));
|
|
249
|
-
const patterns = store.getAllPatterns();
|
|
250
|
-
console.clear();
|
|
251
219
|
console.log();
|
|
252
|
-
console.log(
|
|
253
|
-
|
|
254
|
-
console.log(thick);
|
|
220
|
+
console.log(C.bold(` Project: ${project}`));
|
|
221
|
+
// ─── Personal Layer ──────────────────────────────────────────────────────
|
|
255
222
|
console.log();
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
console.log(C.
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
.slice(0, 5);
|
|
277
|
-
for (const p of top) {
|
|
278
|
-
console.log(C.success(` ✅ ${p.description}`) + C.dim(` (${p.confidence.mean}, ${p.signals?.positive || 0}/${p.signals?.total || 0} signals)`));
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// Blind spots
|
|
223
|
+
console.log(C.bold(' 📂 Personal Layer'));
|
|
224
|
+
console.log(C.dim(' ─────────────────'));
|
|
225
|
+
console.log(` Style: ${C.num(profile.quoteStyle)} quotes, ${C.num(profile.semicolonStyle)} semis, ${C.num(profile.indentStyle)}`);
|
|
226
|
+
console.log(` Code: ${C.num(profile.functionStyle)} functions, ${C.num(profile.asyncStyle)}, ${C.num(profile.errorHandling)} errors`);
|
|
227
|
+
console.log(` Arch: ${C.num(profile.architectureStyle)}, ${C.num(profile.testPattern)} tests`);
|
|
228
|
+
if (profile.strengths.length) {
|
|
229
|
+
for (const s of profile.strengths)
|
|
230
|
+
console.log(` ${C.success('+')} ${s}`);
|
|
231
|
+
}
|
|
232
|
+
if (profile.improvements.length) {
|
|
233
|
+
for (const i of profile.improvements)
|
|
234
|
+
console.log(` ${C.warn('!')} ${i}`);
|
|
235
|
+
}
|
|
236
|
+
// Show .cell/personal/ files
|
|
237
|
+
const personalDir = path.join(layers_1.CELL_DIR, 'personal');
|
|
238
|
+
if (fs.existsSync(personalDir)) {
|
|
239
|
+
const files = fs.readdirSync(personalDir);
|
|
240
|
+
console.log(C.dim(` Files: ${files.join(', ')}`));
|
|
241
|
+
}
|
|
242
|
+
// Behavioral data
|
|
282
243
|
try {
|
|
283
|
-
const
|
|
284
|
-
const
|
|
285
|
-
if (
|
|
286
|
-
console.log(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
console.log(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
244
|
+
const { getBehaviorSummary } = require('./behavioral-tracker');
|
|
245
|
+
const b = getBehaviorSummary(project);
|
|
246
|
+
if (b.totalErrors > 0 || b.totalDecisions > 0 || b.currentContext || b.stuckIssues.length > 0) {
|
|
247
|
+
console.log(C.bold(' Behavior:'));
|
|
248
|
+
if (b.totalErrors > 0)
|
|
249
|
+
console.log(` Errors: ${b.totalErrors} logged`);
|
|
250
|
+
if (b.totalDecisions > 0)
|
|
251
|
+
console.log(` Decisions: ${b.totalDecisions} logged`);
|
|
252
|
+
if (b.currentContext)
|
|
253
|
+
console.log(` Working on: ${b.currentContext.task}`);
|
|
254
|
+
if (b.stuckIssues.length > 0)
|
|
255
|
+
console.log(` Stuck: ${b.stuckIssues.length} issues`);
|
|
294
256
|
}
|
|
295
257
|
}
|
|
296
258
|
catch { }
|
|
297
|
-
//
|
|
259
|
+
// ─── Git Intelligence ────────────────────────────────────────────────────
|
|
298
260
|
try {
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
console.log(C.
|
|
310
|
-
|
|
311
|
-
console.log(C.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
const archSummary = new index_1.ArchitectureEngine().getSummary();
|
|
316
|
-
if (frontendSummary.length > 0 || backendSummary.length > 0 || archSummary.length > 0) {
|
|
317
|
-
console.log(line);
|
|
318
|
-
console.log(C.primary.bold('\n 🏗️ Architecture Intelligence:'));
|
|
319
|
-
for (const s of frontendSummary)
|
|
320
|
-
console.log(C.info(` ${s}`));
|
|
321
|
-
for (const s of backendSummary)
|
|
322
|
-
console.log(C.info(` ${s}`));
|
|
323
|
-
for (const s of archSummary)
|
|
324
|
-
console.log(C.info(` ${s}`));
|
|
325
|
-
}
|
|
326
|
-
if (productivitySummary.length > 0) {
|
|
327
|
-
console.log(line);
|
|
328
|
-
console.log(C.primary.bold('\n ⚡ Productivity Intelligence:'));
|
|
329
|
-
for (const s of productivitySummary)
|
|
330
|
-
console.log(C.info(` ${s}`));
|
|
331
|
-
}
|
|
332
|
-
const knowledgeSummary = new index_1.KnowledgeGraphEngine().getSummary();
|
|
333
|
-
if (knowledgeSummary.length > 0) {
|
|
334
|
-
console.log(line);
|
|
335
|
-
console.log(C.primary.bold('\n 🧠 Knowledge Graph:'));
|
|
336
|
-
for (const s of knowledgeSummary)
|
|
337
|
-
console.log(C.info(` ${s}`));
|
|
338
|
-
}
|
|
339
|
-
const teamAdvSummary = new index_1.TeamAdvancedEngine().getSummary();
|
|
340
|
-
const communityAdvSummary = new index_1.CommunityAdvancedEngine().getSummary();
|
|
341
|
-
if (teamAdvSummary.length > 0) {
|
|
342
|
-
console.log(line);
|
|
343
|
-
console.log(C.primary.bold('\n 👥 Team Advanced:'));
|
|
344
|
-
for (const s of teamAdvSummary)
|
|
345
|
-
console.log(C.info(` ${s}`));
|
|
346
|
-
}
|
|
347
|
-
if (communityAdvSummary.length > 0) {
|
|
348
|
-
console.log(line);
|
|
349
|
-
console.log(C.primary.bold('\n 🌐 Community Advanced:'));
|
|
350
|
-
for (const s of communityAdvSummary)
|
|
351
|
-
console.log(C.info(` ${s}`));
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
catch { }
|
|
355
|
-
console.log();
|
|
356
|
-
console.log(thick);
|
|
357
|
-
console.log();
|
|
358
|
-
});
|
|
359
|
-
program
|
|
360
|
-
.command('taste show')
|
|
361
|
-
.description('Display your cell.md profile')
|
|
362
|
-
.action(() => {
|
|
363
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
364
|
-
const mdPath = path.join(cellDir, 'cell.md');
|
|
365
|
-
if (!fs.existsSync(mdPath)) {
|
|
366
|
-
console.log('❌ No taste profile found. Run `cell init` first, then start coding.');
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
console.log(fs.readFileSync(mdPath, 'utf-8'));
|
|
370
|
-
});
|
|
371
|
-
program
|
|
372
|
-
.command('taste reset')
|
|
373
|
-
.description('Reset all learned patterns')
|
|
374
|
-
.action(() => {
|
|
375
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
376
|
-
if (!fs.existsSync(cellDir)) {
|
|
377
|
-
console.log('❌ Cell not initialized.');
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
const store = new index_1.PatternStore(cellDir);
|
|
381
|
-
store.clear();
|
|
382
|
-
console.log('✅ All patterns reset. Cell will relearn from scratch.');
|
|
383
|
-
});
|
|
384
|
-
program
|
|
385
|
-
.command('learn')
|
|
386
|
-
.description('Feed a code edit to Cell for learning')
|
|
387
|
-
.option('-o, --original <code>', 'Original AI-generated code')
|
|
388
|
-
.option('-e, --edited <code>', 'Your edited version')
|
|
389
|
-
.option('-a, --accept', 'Mark as accepted (no edits)')
|
|
390
|
-
.option('-r, --reject', 'Mark as rejected')
|
|
391
|
-
.option('--audit', 'Run security and error analysis on edited code')
|
|
392
|
-
.action((options) => {
|
|
393
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
394
|
-
if (!fs.existsSync(cellDir)) {
|
|
395
|
-
console.log('❌ Cell not initialized. Run `cell init` first.');
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
const capture = new index_1.SignalCapture();
|
|
399
|
-
const cascade = new index_1.ExtractionCascade();
|
|
400
|
-
const store = new index_1.PatternStore(cellDir);
|
|
401
|
-
const context = {
|
|
402
|
-
language: 'typescript',
|
|
403
|
-
framework: 'unknown',
|
|
404
|
-
fileType: 'unknown',
|
|
405
|
-
strictness: 'moderate',
|
|
406
|
-
projectId: path.basename(process.cwd()),
|
|
407
|
-
};
|
|
408
|
-
if (options.accept && options.original) {
|
|
409
|
-
const signal = capture.captureAccept(options.original, context);
|
|
410
|
-
console.log(`✅ Accept signal captured (session: ${signal.sessionId})`);
|
|
411
|
-
}
|
|
412
|
-
else if (options.reject && options.original) {
|
|
413
|
-
const signal = capture.captureReject(options.original, context);
|
|
414
|
-
console.log(`❌ Reject signal captured (session: ${signal.sessionId})`);
|
|
415
|
-
}
|
|
416
|
-
else if (options.original && options.edited) {
|
|
417
|
-
const signal = capture.captureEditDiff(options.original, options.edited, context);
|
|
418
|
-
const result = cascade.extract(options.original, options.edited, context.language);
|
|
419
|
-
console.log(`📝 Edit diff captured (session: ${signal.sessionId})`);
|
|
420
|
-
console.log(` Step used: ${result.stepUsed}`);
|
|
421
|
-
console.log(` Latency: ${result.latencyMs}ms`);
|
|
422
|
-
console.log(` Patterns found: ${result.patterns.length}`);
|
|
423
|
-
for (const p of result.patterns) {
|
|
424
|
-
const pattern = store.addOrUpdatePattern(p.category, p.description, p.from, p.to, true, p.conditions, 'global', result.stepUsed, result.language);
|
|
425
|
-
console.log(` → ${p.description} (confidence: ${pattern.confidence.mean}, quality: ${pattern.quality.score})`);
|
|
426
|
-
}
|
|
427
|
-
store.save();
|
|
428
|
-
try {
|
|
429
|
-
new index_1.CellStore().syncFromPatternStore(store);
|
|
430
|
-
}
|
|
431
|
-
catch { }
|
|
432
|
-
console.log(`\n✅ Taste profile updated. ${store.getPatternCount()} patterns total.`);
|
|
433
|
-
if (options.audit && options.edited) {
|
|
434
|
-
const auditResult = cascade.audit(options.edited);
|
|
435
|
-
if (auditResult.security.length > 0 || auditResult.errors.length > 0) {
|
|
436
|
-
console.log(`\n🔍 Code audit results:`);
|
|
437
|
-
for (const s of auditResult.security) {
|
|
438
|
-
console.log(` ⚠ [${s.severity}] ${s.type}:${s.line} ${s.message}`);
|
|
261
|
+
const { buildDeveloperIntelligence } = require('./developer-intelligence');
|
|
262
|
+
const gitIntel = buildDeveloperIntelligence(process.cwd());
|
|
263
|
+
if (gitIntel) {
|
|
264
|
+
console.log();
|
|
265
|
+
console.log(C.bold(' 🧠 Git Intelligence'));
|
|
266
|
+
console.log(C.dim(' ──────────────────'));
|
|
267
|
+
console.log(` Score: ${C.num(String(gitIntel.behavioralScore))}/100`);
|
|
268
|
+
if (gitIntel.timeSummary)
|
|
269
|
+
console.log(C.dim(` ${gitIntel.timeSummary}`));
|
|
270
|
+
if (gitIntel.journeySummary)
|
|
271
|
+
console.log(C.dim(` ${gitIntel.journeySummary}`));
|
|
272
|
+
if (gitIntel.topBlindSpots.length > 0) {
|
|
273
|
+
console.log(C.bold(' Top Blind Spots:'));
|
|
274
|
+
for (const bs of gitIntel.topBlindSpots.slice(0, 3)) {
|
|
275
|
+
console.log(` ${C.warn('!')} ${bs}`);
|
|
439
276
|
}
|
|
440
|
-
|
|
441
|
-
|
|
277
|
+
}
|
|
278
|
+
if (gitIntel.topMistakes.length > 0) {
|
|
279
|
+
console.log(C.bold(' Repeat Mistakes:'));
|
|
280
|
+
for (const m of gitIntel.topMistakes.slice(0, 3)) {
|
|
281
|
+
console.log(` ${C.warn('↻')} ${m}`);
|
|
442
282
|
}
|
|
443
283
|
}
|
|
444
|
-
|
|
445
|
-
|
|
284
|
+
if (gitIntel.topStrengths.length > 0) {
|
|
285
|
+
for (const s of gitIntel.topStrengths.slice(0, 3)) {
|
|
286
|
+
console.log(` ${C.success('+')} ${s}`);
|
|
287
|
+
}
|
|
446
288
|
}
|
|
447
289
|
}
|
|
448
290
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
console.log('❌ Cell not initialized. Run `cell init` first.');
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
const username = options.username || 'anonymous';
|
|
464
|
-
const store = new index_1.PatternStore(cellDir);
|
|
465
|
-
const composer = new index_1.TeamComposer(store, cellDir);
|
|
466
|
-
composer.pushTaste(username);
|
|
467
|
-
console.log(`✅ Taste pushed for ${username}.`);
|
|
468
|
-
console.log(` Team members: ${composer.getTeamMembers().join(', ') || 'none yet'}`);
|
|
469
|
-
});
|
|
470
|
-
program
|
|
471
|
-
.command('pull')
|
|
472
|
-
.description('Pull team or member taste')
|
|
473
|
-
.option('-u, --username <name>', 'Pull specific member taste')
|
|
474
|
-
.option('--team', 'Pull full team composite')
|
|
475
|
-
.action((options) => {
|
|
476
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
477
|
-
if (!fs.existsSync(cellDir)) {
|
|
478
|
-
console.log('❌ Cell not initialized.');
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
const store = new index_1.PatternStore(cellDir);
|
|
482
|
-
const composer = new index_1.TeamComposer(store, cellDir);
|
|
483
|
-
if (options.username) {
|
|
484
|
-
const taste = composer.pullTaste(options.username);
|
|
485
|
-
if (!taste) {
|
|
486
|
-
console.log(`❌ No taste found for ${options.username}.`);
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
console.log(`📥 Pulled taste from ${options.username}:`);
|
|
490
|
-
console.log(` Patterns: ${taste.patterns.length}`);
|
|
491
|
-
console.log(` Signals: ${taste.totalSignals}`);
|
|
492
|
-
}
|
|
493
|
-
else {
|
|
494
|
-
const taste = composer.pullTeamTaste();
|
|
495
|
-
if (!taste) {
|
|
496
|
-
console.log('❌ No team taste available. Have teammates pushed yet?');
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
console.log(`📥 Pulled team taste (${composer.getTeamMembers().length} members):`);
|
|
500
|
-
console.log(` Patterns: ${taste.patterns.length}`);
|
|
501
|
-
console.log(` Total signals: ${taste.totalSignals}`);
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
program
|
|
505
|
-
.command('vote')
|
|
506
|
-
.description('Vote on a pattern conflict')
|
|
507
|
-
.option('-p, --pattern <id>', 'Pattern conflict ID (e.g., p_abc_vs_p_def)')
|
|
508
|
-
.option('-v, --vote <choice>', 'Your vote: A, B, or none')
|
|
509
|
-
.option('--status', 'Show vote status')
|
|
510
|
-
.action((options) => {
|
|
511
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
512
|
-
if (!fs.existsSync(cellDir)) {
|
|
513
|
-
console.log('❌ Cell not initialized.');
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
const detector = new index_1.ConflictDetector(cellDir);
|
|
517
|
-
if (options.status && options.pattern) {
|
|
518
|
-
const sessions = fs.existsSync(detector['voteStorePath'])
|
|
519
|
-
? JSON.parse(fs.readFileSync(detector['voteStorePath'], 'utf-8'))
|
|
520
|
-
: [];
|
|
521
|
-
const session = sessions.find((s) => s.patternId === options.pattern);
|
|
522
|
-
if (!session) {
|
|
523
|
-
console.log('❌ Vote session not found.');
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
console.log(detector.getVoteStatus(session));
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
if (options.pattern && options.vote) {
|
|
530
|
-
const username = 'anonymous';
|
|
531
|
-
const session = detector.castVote(options.pattern, username, options.vote);
|
|
532
|
-
if (!session) {
|
|
533
|
-
console.log('❌ Vote failed. Check pattern ID and deadline.');
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
console.log(`✅ Vote cast: ${options.vote}`);
|
|
537
|
-
console.log(detector.getVoteStatus(session));
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
console.log('Usage: cell taste vote --pattern "X_vs_Y" --vote A');
|
|
541
|
-
console.log(' cell taste vote --pattern "X_vs_Y" --status');
|
|
542
|
-
});
|
|
543
|
-
program
|
|
544
|
-
.command('community')
|
|
545
|
-
.description('Show community prior patterns')
|
|
546
|
-
.action(() => {
|
|
547
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
548
|
-
if (!fs.existsSync(cellDir)) {
|
|
549
|
-
console.log('❌ Cell not initialized.');
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
const prior = new index_1.CommunityPrior(cellDir);
|
|
553
|
-
if (prior.getPatternCount() === 0) {
|
|
554
|
-
console.log('🌱 Generating synthetic community seed...');
|
|
555
|
-
prior.generateSyntheticSeed();
|
|
556
|
-
}
|
|
557
|
-
console.log(`\n🌍 ${prior.getDisplayLabel()}`);
|
|
558
|
-
console.log(` Total patterns: ${prior.getPatternCount()}`);
|
|
559
|
-
console.log(` Synthetic: ${prior.getSyntheticPatterns().length}`);
|
|
560
|
-
console.log(` Live-learned: ${prior.getLivePatterns().length}`);
|
|
561
|
-
const patterns = prior.getPatterns(0.5);
|
|
562
|
-
if (patterns.length > 0) {
|
|
563
|
-
console.log('\nTop community patterns:');
|
|
564
|
-
for (const p of patterns.slice(0, 5)) {
|
|
565
|
-
const marker = prior.getSyntheticPatterns().some(sp => sp.patternId === p.patternId) ? '🧪' : '👥';
|
|
566
|
-
console.log(` ${marker} ${p.description} (${p.confidence.mean})`);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
console.log('');
|
|
570
|
-
});
|
|
571
|
-
program
|
|
572
|
-
.command('next')
|
|
573
|
-
.description('Predict next coding action')
|
|
574
|
-
.option('-a, --action <name>', 'Record an action for sequence learning')
|
|
575
|
-
.option('-f, --feedback <action>', 'Give feedback on a prediction (was it useful?)')
|
|
576
|
-
.action((options) => {
|
|
577
|
-
const predictor = new index_1.NextActionPredictor();
|
|
578
|
-
if (options.action) {
|
|
579
|
-
predictor.recordAction(options.action);
|
|
580
|
-
console.log(`✅ Recorded action: ${options.action}`);
|
|
581
|
-
const predictions = predictor.predictNext([]);
|
|
582
|
-
if (predictions.length > 0) {
|
|
583
|
-
console.log('\nPredicted next actions:');
|
|
584
|
-
for (const p of predictions) {
|
|
585
|
-
console.log(` → ${p.description} (confidence: ${p.confidence})`);
|
|
291
|
+
catch { }
|
|
292
|
+
// ─── Predictions ─────────────────────────────────────────────────────────
|
|
293
|
+
try {
|
|
294
|
+
const { getQuickWarnings } = require('./predictive-engine');
|
|
295
|
+
const warnings = getQuickWarnings(project);
|
|
296
|
+
if (warnings.length > 0) {
|
|
297
|
+
console.log();
|
|
298
|
+
console.log(C.bold(' 🔮 Predictions'));
|
|
299
|
+
console.log(C.dim(' ──────────────'));
|
|
300
|
+
for (const w of warnings) {
|
|
301
|
+
console.log(` ${w}`);
|
|
586
302
|
}
|
|
587
|
-
const bulk = predictor.getBulkSuggestion(predictions);
|
|
588
|
-
if (bulk)
|
|
589
|
-
console.log(` ⚡ ${bulk.description}`);
|
|
590
|
-
}
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
if (options.feedback) {
|
|
594
|
-
predictor.recordFeedback(options.feedback, true);
|
|
595
|
-
console.log(`✅ Feedback recorded for: ${options.feedback}`);
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
const predictions = predictor.predictNext([]);
|
|
599
|
-
console.log('Predicted next actions:');
|
|
600
|
-
for (const p of predictions) {
|
|
601
|
-
console.log(` → ${p.description} (confidence: ${p.confidence})`);
|
|
602
|
-
}
|
|
603
|
-
});
|
|
604
|
-
program
|
|
605
|
-
.command('branch')
|
|
606
|
-
.description('Pre-generate files from git branch name')
|
|
607
|
-
.option('-b, --branch <name>', 'Branch name (e.g., feature/payment-gateway)')
|
|
608
|
-
.action((options) => {
|
|
609
|
-
if (!options.branch) {
|
|
610
|
-
console.log('❌ Provide --branch name');
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
const generator = new index_1.GitBranchPreGenerator();
|
|
614
|
-
const summary = generator.getIntentSummary(options.branch);
|
|
615
|
-
console.log(`📋 ${summary}`);
|
|
616
|
-
const files = generator.generateFiles(options.branch, []);
|
|
617
|
-
for (const f of files) {
|
|
618
|
-
console.log(`\n--- ${f.path} ---`);
|
|
619
|
-
console.log(f.content);
|
|
620
|
-
}
|
|
621
|
-
});
|
|
622
|
-
program
|
|
623
|
-
.command('gentests')
|
|
624
|
-
.description('Generate test cases for a function')
|
|
625
|
-
.option('-c, --code <code>', 'Function code to analyze')
|
|
626
|
-
.action((options) => {
|
|
627
|
-
if (!options.code) {
|
|
628
|
-
console.log('❌ Provide --code with function signature');
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
const anticipator = new index_1.TestAnticipator();
|
|
632
|
-
const tests = anticipator.generateTests(options.code);
|
|
633
|
-
console.log(`Generated ${tests.length} test cases:\n`);
|
|
634
|
-
for (const t of tests) {
|
|
635
|
-
console.log(`[${t.type}] ${t.name}`);
|
|
636
|
-
console.log(t.code);
|
|
637
|
-
console.log('');
|
|
638
|
-
}
|
|
639
|
-
});
|
|
640
|
-
program
|
|
641
|
-
.command('errors')
|
|
642
|
-
.description('Predict potential errors in code')
|
|
643
|
-
.option('-c, --code <code>', 'Code to analyze')
|
|
644
|
-
.action((options) => {
|
|
645
|
-
if (!options.code) {
|
|
646
|
-
console.log('❌ Provide --code to analyze');
|
|
647
|
-
return;
|
|
648
|
-
}
|
|
649
|
-
const predictor = new index_1.ErrorPredictor();
|
|
650
|
-
const predictions = predictor.predict(options.code);
|
|
651
|
-
if (predictions.length === 0) {
|
|
652
|
-
console.log('✅ No potential errors detected.');
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
console.log(`Found ${predictions.length} potential errors:\n`);
|
|
656
|
-
for (const p of predictions) {
|
|
657
|
-
console.log(`[${p.severity}] Line ${p.line}: ${p.message}`);
|
|
658
|
-
console.log(` Fix: ${predictor.getQuickFix(p)}`);
|
|
659
|
-
console.log('');
|
|
660
|
-
}
|
|
661
|
-
});
|
|
662
|
-
program
|
|
663
|
-
.command('buildcheck')
|
|
664
|
-
.description('Predict build failures (TS, ESLint, tests)')
|
|
665
|
-
.option('-c, --code <code>', 'Code to analyze')
|
|
666
|
-
.action((options) => {
|
|
667
|
-
if (!options.code) {
|
|
668
|
-
console.log('❌ Provide --code to analyze');
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
const predictor = new index_1.BuildFailurePredictor();
|
|
672
|
-
const result = predictor.predictAll(options.code);
|
|
673
|
-
const all = [...result.tsErrors, ...result.eslintViolations, ...result.testFailures];
|
|
674
|
-
if (all.length === 0) {
|
|
675
|
-
console.log('✅ No build failures predicted.');
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
console.log(`Predicted ${all.length} build failures:\n`);
|
|
679
|
-
for (const p of all) {
|
|
680
|
-
const auto = p.autoFixable ? ' [AUTO-FIXABLE]' : '';
|
|
681
|
-
console.log(`[${p.type}] Line ${p.line}: ${p.message}${auto}`);
|
|
682
|
-
if (p.fix)
|
|
683
|
-
console.log(` Fix: ${p.fix}`);
|
|
684
|
-
console.log('');
|
|
685
|
-
}
|
|
686
|
-
const stats = predictor.getStats(all);
|
|
687
|
-
console.log(`Summary: ${stats.total} total, ${stats.autoFixable} auto-fixable`);
|
|
688
|
-
});
|
|
689
|
-
program
|
|
690
|
-
.command('mergecheck')
|
|
691
|
-
.description('Predict merge conflicts between branches')
|
|
692
|
-
.option('-a, --diff-a <diff>', 'Diff from branch A')
|
|
693
|
-
.option('-b, --diff-b <diff>', 'Diff from branch B')
|
|
694
|
-
.action((options) => {
|
|
695
|
-
if (!options.diffA || !options.diffB) {
|
|
696
|
-
console.log('❌ Provide --diff-a and --diff-b');
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
const predictor = new index_1.MergeConflictPredictor();
|
|
700
|
-
const conflicts = predictor.predictConflicts(options.diffA, options.diffB);
|
|
701
|
-
if (conflicts.length === 0) {
|
|
702
|
-
console.log('✅ No merge conflicts predicted.');
|
|
703
|
-
return;
|
|
704
|
-
}
|
|
705
|
-
console.log(`Predicted ${conflicts.length} merge conflicts:\n`);
|
|
706
|
-
for (const c of conflicts) {
|
|
707
|
-
console.log(`[${c.type}] ${c.file}:${c.line} (confidence: ${c.confidence})`);
|
|
708
|
-
console.log(` ${c.suggestion}`);
|
|
709
|
-
console.log('');
|
|
710
|
-
}
|
|
711
|
-
});
|
|
712
|
-
program
|
|
713
|
-
.command('scan')
|
|
714
|
-
.description('Scan code for security vulnerabilities')
|
|
715
|
-
.option('-c, --code <code>', 'Code to scan')
|
|
716
|
-
.action((options) => {
|
|
717
|
-
if (!options.code) {
|
|
718
|
-
console.log('❌ Provide --code to scan');
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
const predictor = new index_1.SecurityPredictor();
|
|
722
|
-
const predictions = predictor.predict(options.code);
|
|
723
|
-
if (predictions.length === 0) {
|
|
724
|
-
console.log('✅ No security vulnerabilities detected.');
|
|
725
|
-
return;
|
|
726
|
-
}
|
|
727
|
-
console.log(`Found ${predictions.length} security issues:\n`);
|
|
728
|
-
for (const p of predictions) {
|
|
729
|
-
console.log(`[${p.severity}] ${p.type}: Line ${p.line}`);
|
|
730
|
-
console.log(` ${p.message}`);
|
|
731
|
-
console.log(` Fix: ${p.sanitizedVersion}`);
|
|
732
|
-
console.log('');
|
|
733
|
-
}
|
|
734
|
-
});
|
|
735
|
-
program
|
|
736
|
-
.command('perf')
|
|
737
|
-
.description('Analyze code for performance issues')
|
|
738
|
-
.option('-c, --code <code>', 'Code to analyze')
|
|
739
|
-
.action((options) => {
|
|
740
|
-
if (!options.code) {
|
|
741
|
-
console.log('❌ Provide --code to analyze');
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
const predictor = new index_1.PerformancePredictor();
|
|
745
|
-
const predictions = predictor.predict(options.code);
|
|
746
|
-
if (predictions.length === 0) {
|
|
747
|
-
console.log('✅ No performance issues detected.');
|
|
748
|
-
return;
|
|
749
|
-
}
|
|
750
|
-
console.log(`Found ${predictions.length} performance issues:\n`);
|
|
751
|
-
for (const p of predictions) {
|
|
752
|
-
console.log(`[${p.severity}] ${p.type}: Line ${p.line}`);
|
|
753
|
-
console.log(` ${p.message}`);
|
|
754
|
-
console.log(` Fix: ${p.suggestion}`);
|
|
755
|
-
console.log('');
|
|
756
|
-
}
|
|
757
|
-
});
|
|
758
|
-
program
|
|
759
|
-
.command('snapshot')
|
|
760
|
-
.description('Capture or restore project context')
|
|
761
|
-
.option('-p, --project <id>', 'Project ID')
|
|
762
|
-
.option('-r, --restore', 'Restore last snapshot')
|
|
763
|
-
.action((options) => {
|
|
764
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
765
|
-
const restore = new index_1.ContextRestore(cellDir);
|
|
766
|
-
if (options.restore && options.project) {
|
|
767
|
-
const snapshot = restore.restore(options.project);
|
|
768
|
-
if (!snapshot) {
|
|
769
|
-
console.log('❌ No snapshot found.');
|
|
770
|
-
return;
|
|
771
303
|
}
|
|
772
|
-
console.log(restore.getResumePrompt(snapshot));
|
|
773
|
-
return;
|
|
774
|
-
}
|
|
775
|
-
if (options.project) {
|
|
776
|
-
restore.capture(options.project, [], '', 0, [], '', 'main');
|
|
777
|
-
console.log(`✅ Snapshot captured for ${options.project}`);
|
|
778
|
-
return;
|
|
779
304
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
.
|
|
789
|
-
.option('-s, --source <id>', 'Source project ID')
|
|
790
|
-
.option('-t, --target <id>', 'Target project ID')
|
|
791
|
-
.action((options) => {
|
|
792
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
793
|
-
const store = new index_1.PatternStore(cellDir);
|
|
794
|
-
const sync = new index_1.CrossProjectSync(store, cellDir);
|
|
795
|
-
if (options.source && options.target) {
|
|
796
|
-
const adapted = sync.generateAdaptedPatterns(options.source, options.target);
|
|
797
|
-
console.log(`${adapted.length} patterns compatible with ${options.target}:`);
|
|
798
|
-
for (const a of adapted) {
|
|
799
|
-
console.log(` ${a.original.description} (compatibility: ${a.compatibilityScore})`);
|
|
305
|
+
catch { }
|
|
306
|
+
// ─── Team Layer ──────────────────────────────────────────────────────────
|
|
307
|
+
console.log();
|
|
308
|
+
console.log(C.bold(' 👥 Team Layer'));
|
|
309
|
+
console.log(C.dim(' ─────────────'));
|
|
310
|
+
const teamData = (0, layers_1.getTeamMembers)();
|
|
311
|
+
if (teamData && teamData.members && teamData.members.length > 0) {
|
|
312
|
+
for (const m of teamData.members) {
|
|
313
|
+
console.log(` ${C.success('•')} ${m.name} — ${m.role}`);
|
|
800
314
|
}
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
const stats = sync.getSyncStats();
|
|
804
|
-
console.log(`Cross-project sync: ${stats.projects} projects, ${stats.totalPatterns} patterns`);
|
|
805
|
-
});
|
|
806
|
-
program
|
|
807
|
-
.command('solutions')
|
|
808
|
-
.description('Search solution index')
|
|
809
|
-
.option('-q, --query <text>', 'Search query')
|
|
810
|
-
.option('-a, --add <title>', 'Add a solution')
|
|
811
|
-
.option('-d, --desc <text>', 'Solution description')
|
|
812
|
-
.option('-p, --project <id>', 'Project ID')
|
|
813
|
-
.option('--stats', 'Show solution index stats')
|
|
814
|
-
.action((options) => {
|
|
815
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
816
|
-
const index = new index_1.SolutionIndex(cellDir);
|
|
817
|
-
if (options.stats) {
|
|
818
|
-
const stats = index.getStats();
|
|
819
|
-
console.log(`Solution index: ${stats.projects} projects, ${stats.totalSolutions} solutions`);
|
|
820
|
-
console.log(`Top tags: ${stats.topTags.join(', ')}`);
|
|
821
|
-
if (index.isColdStart())
|
|
822
|
-
console.log(index.getColdStartMessage());
|
|
823
|
-
return;
|
|
824
315
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
console.log(`✅ Solution added: ${sol.id}`);
|
|
828
|
-
return;
|
|
316
|
+
else {
|
|
317
|
+
console.log(C.dim(' No team members. Add: cell team add <name>'));
|
|
829
318
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
console.log(`
|
|
833
|
-
for (const s of results) {
|
|
834
|
-
console.log(` 📋 ${s.title} (${s.projectId})`);
|
|
835
|
-
console.log(` ${s.description}`);
|
|
836
|
-
}
|
|
837
|
-
return;
|
|
319
|
+
const teamPatterns = (0, layers_1.getTeamPatterns)();
|
|
320
|
+
if (teamPatterns && teamPatterns.patterns && teamPatterns.patterns.length > 0) {
|
|
321
|
+
console.log(C.dim(` Shared patterns: ${teamPatterns.patterns.length}`));
|
|
838
322
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
});
|
|
843
|
-
program
|
|
844
|
-
.command('langswitch')
|
|
845
|
-
.description('Get language switch guide')
|
|
846
|
-
.option('-f, --from <lang>', 'Source language')
|
|
847
|
-
.option('-t, --to <lang>', 'Target language')
|
|
848
|
-
.action((options) => {
|
|
849
|
-
const assistant = new index_1.LanguageSwitchAssistant();
|
|
850
|
-
if (options.from && options.to) {
|
|
851
|
-
const guide = assistant.getGuide(options.from, options.to);
|
|
852
|
-
if (!guide) {
|
|
853
|
-
console.log(`❌ No guide for ${options.from}→${options.to}`);
|
|
854
|
-
console.log(`Available: ${assistant.getAvailableTransitions().join(', ')}`);
|
|
855
|
-
return;
|
|
856
|
-
}
|
|
857
|
-
console.log(`\n📖 ${guide.from} → ${guide.to} Guide\n`);
|
|
858
|
-
console.log('⚠️ Gotchas:');
|
|
859
|
-
for (const g of guide.gotchas)
|
|
860
|
-
console.log(` • ${g}`);
|
|
861
|
-
console.log('\n💡 Style Tips:');
|
|
862
|
-
for (const t of guide.styleTips)
|
|
863
|
-
console.log(` • ${t}`);
|
|
864
|
-
return;
|
|
323
|
+
const teamBlinds = (0, layers_1.getTeamBlindSpots)();
|
|
324
|
+
if (teamBlinds && teamBlinds.blindSpots && teamBlinds.blindSpots.length > 0) {
|
|
325
|
+
console.log(C.warn(` Blind spots: ${teamBlinds.blindSpots.length}`));
|
|
865
326
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
.
|
|
873
|
-
.description('Check for interruption and resume')
|
|
874
|
-
.action(() => {
|
|
875
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
876
|
-
const recovery = new index_1.InterruptionRecovery(cellDir);
|
|
877
|
-
const interruption = recovery.detectInterruption();
|
|
878
|
-
if (interruption) {
|
|
879
|
-
console.log(recovery.getContinuePrompt(interruption));
|
|
880
|
-
console.log(recovery.getSummaryPrompt(interruption));
|
|
881
|
-
console.log(recovery.getRestartPrompt());
|
|
327
|
+
// ─── Community Layer ─────────────────────────────────────────────────────
|
|
328
|
+
console.log();
|
|
329
|
+
console.log(C.bold(' 🌐 Community Layer'));
|
|
330
|
+
console.log(C.dim(' ──────────────────'));
|
|
331
|
+
const commPatterns = (0, layers_1.getCommunityPatterns)();
|
|
332
|
+
if (commPatterns && commPatterns.patterns && commPatterns.patterns.length > 0) {
|
|
333
|
+
console.log(C.dim(` Patterns shared: ${commPatterns.patterns.length}`));
|
|
882
334
|
}
|
|
883
335
|
else {
|
|
884
|
-
console.log('
|
|
336
|
+
console.log(C.dim(' No community patterns yet. Run: cell community'));
|
|
885
337
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
.
|
|
889
|
-
.description('Generate teammate handoff summary')
|
|
890
|
-
.option('-t, --teammate <name>', 'Teammate name')
|
|
891
|
-
.option('-b, --branch <name>', 'Branch name')
|
|
892
|
-
.action((options) => {
|
|
893
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
894
|
-
const detector = new index_1.HandoffDetector(cellDir);
|
|
895
|
-
if (options.teammate && options.branch) {
|
|
896
|
-
const isAbsent = detector.detectAbsence(options.teammate, options.branch);
|
|
897
|
-
if (isAbsent) {
|
|
898
|
-
const summary = detector.generateReturnSummary(options.teammate, options.branch, [], [], [], new Date().toISOString());
|
|
899
|
-
console.log(detector.getReturnPrompt(summary));
|
|
900
|
-
}
|
|
901
|
-
else {
|
|
902
|
-
console.log(`✅ ${options.teammate} is active on ${options.branch}.`);
|
|
903
|
-
}
|
|
904
|
-
return;
|
|
338
|
+
const commTrends = (0, layers_1.getCommunityTrends)();
|
|
339
|
+
if (commTrends && commTrends.trends && commTrends.trends.length > 0) {
|
|
340
|
+
console.log(C.dim(` Trends: ${commTrends.trends.length}`));
|
|
905
341
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
.command('silos')
|
|
910
|
-
.description('Detect knowledge silos')
|
|
911
|
-
.option('-m, --modules <json>', 'Module→contributors mapping as JSON')
|
|
912
|
-
.action((options) => {
|
|
913
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
914
|
-
const detector = new index_1.KnowledgeSiloDetector(cellDir);
|
|
915
|
-
if (options.modules) {
|
|
916
|
-
const mapping = JSON.parse(options.modules);
|
|
917
|
-
const reports = detector.analyzeProject(mapping);
|
|
918
|
-
const risks = detector.getTopRisks(reports);
|
|
919
|
-
console.log(`${reports.length} modules analyzed. ${risks.length} at risk:\n`);
|
|
920
|
-
for (const r of risks) {
|
|
921
|
-
console.log(`🔴 ${r.module} (risk: ${r.riskScore}, bus factor: ${r.busFactor})`);
|
|
922
|
-
console.log(` ${r.recommendation}`);
|
|
923
|
-
}
|
|
924
|
-
return;
|
|
925
|
-
}
|
|
926
|
-
const saved = detector.loadReport();
|
|
927
|
-
if (saved.length === 0) {
|
|
928
|
-
console.log('No silo reports. Run: cell silos --modules \'{"auth":["alice"],"api":["bob","carol"]}\'');
|
|
929
|
-
return;
|
|
342
|
+
const commRank = (0, layers_1.getCommunityRankings)();
|
|
343
|
+
if (commRank && commRank.rankings && commRank.rankings.length > 0) {
|
|
344
|
+
console.log(C.dim(` Rankings: ${commRank.rankings.length}`));
|
|
930
345
|
}
|
|
931
|
-
console.log(
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
.
|
|
936
|
-
.
|
|
937
|
-
.
|
|
938
|
-
.
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
console.log('\n✅ No issues detected.');
|
|
346
|
+
console.log();
|
|
347
|
+
}
|
|
348
|
+
// ─── cell team ──────────────────────────────────────────────────────────────
|
|
349
|
+
function doTeam() {
|
|
350
|
+
console.log();
|
|
351
|
+
console.log(C.bold(' Cell Team'));
|
|
352
|
+
console.log(C.dim(' ─────────'));
|
|
353
|
+
console.log();
|
|
354
|
+
const db = (0, database_1.getDb)();
|
|
355
|
+
db.exec(`
|
|
356
|
+
CREATE TABLE IF NOT EXISTS team_members (
|
|
357
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
358
|
+
name TEXT NOT NULL,
|
|
359
|
+
role TEXT DEFAULT 'developer',
|
|
360
|
+
joined_at TEXT DEFAULT (datetime('now'))
|
|
361
|
+
)
|
|
362
|
+
`);
|
|
363
|
+
const sub = args[1] || '';
|
|
364
|
+
// ─── team push ──────────────────────────────────────────────────────
|
|
365
|
+
if (sub === 'push') {
|
|
366
|
+
console.log(C.primary(' Pushing your patterns to team...'));
|
|
367
|
+
const { teamPush } = require('./team-git');
|
|
368
|
+
const name = args[2];
|
|
369
|
+
if (!name) {
|
|
370
|
+
console.log(C.warn(' Usage: cell team push <your-name> [role]'));
|
|
371
|
+
console.log();
|
|
372
|
+
return;
|
|
959
373
|
}
|
|
374
|
+
const role = args[3] || 'developer';
|
|
375
|
+
const result = teamPush(name, role);
|
|
376
|
+
console.log(result.success ? C.success(` ${result.message}`) : C.warn(` ${result.message}`));
|
|
377
|
+
console.log();
|
|
960
378
|
return;
|
|
961
379
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
.option('-n, --plan <items>', 'Planned items (comma-separated)')
|
|
971
|
-
.action((options) => {
|
|
972
|
-
const generator = new index_1.StandupGenerator();
|
|
973
|
-
if (options.completed || options.progress || options.plan) {
|
|
974
|
-
const completed = options.completed ? options.completed.split(',') : [];
|
|
975
|
-
const inProgress = options.progress ? options.progress.split(',') : [];
|
|
976
|
-
const blocked = options.blocked ? options.blocked.split(',') : [];
|
|
977
|
-
const plan = options.plan ? options.plan.split(',') : [];
|
|
978
|
-
const entry = generator.generateDaily(completed, inProgress, blocked, plan);
|
|
979
|
-
console.log(generator.formatStandup(entry));
|
|
980
|
-
return;
|
|
981
|
-
}
|
|
982
|
-
const summary = generator.getWeeklySummary();
|
|
983
|
-
console.log(summary);
|
|
984
|
-
});
|
|
985
|
-
program
|
|
986
|
-
.command('offline')
|
|
987
|
-
.description('Check offline queue status')
|
|
988
|
-
.option('--heartbeat', 'Send engine heartbeat')
|
|
989
|
-
.action((options) => {
|
|
990
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
991
|
-
const queue = new index_1.OfflineQueue(cellDir);
|
|
992
|
-
if (options.heartbeat) {
|
|
993
|
-
queue.heartbeat();
|
|
994
|
-
console.log('✅ Heartbeat sent. Engine is ONLINE.');
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
const status = queue.checkEngineHealth();
|
|
998
|
-
console.log(`Engine: ${status.state}`);
|
|
999
|
-
console.log(`Queue size: ${queue.getQueueSize()}`);
|
|
1000
|
-
console.log(queue.getDegradedMessage(status));
|
|
1001
|
-
});
|
|
1002
|
-
program
|
|
1003
|
-
.command('deadcode')
|
|
1004
|
-
.description('Detect dead code in a file')
|
|
1005
|
-
.option('-c, --code <code>', 'Code to analyze')
|
|
1006
|
-
.option('-f, --file <name>', 'File name')
|
|
1007
|
-
.action((options) => {
|
|
1008
|
-
if (!options.code || !options.file) {
|
|
1009
|
-
console.log('❌ Provide --code and --file');
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
const detector = new index_1.DeadCodeDetector();
|
|
1013
|
-
const reports = detector.detectAll(options.code, options.file);
|
|
1014
|
-
if (reports.length === 0) {
|
|
1015
|
-
console.log('✅ No dead code detected.');
|
|
1016
|
-
return;
|
|
1017
|
-
}
|
|
1018
|
-
console.log(`Found ${reports.length} dead code items:\n`);
|
|
1019
|
-
for (const r of reports) {
|
|
1020
|
-
console.log(`[${r.type}] ${r.file}:${r.line} — ${r.name}`);
|
|
1021
|
-
console.log(` ${r.suggestion}`);
|
|
1022
|
-
}
|
|
1023
|
-
});
|
|
1024
|
-
program
|
|
1025
|
-
.command('cycles')
|
|
1026
|
-
.description('Detect circular dependencies')
|
|
1027
|
-
.option('-i, --imports <json>', 'Import edges as JSON array of {from,to}')
|
|
1028
|
-
.action((options) => {
|
|
1029
|
-
if (!options.imports) {
|
|
1030
|
-
console.log('❌ Provide --imports as JSON');
|
|
1031
|
-
return;
|
|
1032
|
-
}
|
|
1033
|
-
const detector = new index_1.CircularDependencyDetector();
|
|
1034
|
-
const edges = JSON.parse(options.imports);
|
|
1035
|
-
const graph = detector.buildGraph(edges);
|
|
1036
|
-
const cycles = detector.detectCycles(graph);
|
|
1037
|
-
if (cycles.length === 0) {
|
|
1038
|
-
console.log('✅ No circular dependencies detected.');
|
|
1039
|
-
return;
|
|
1040
|
-
}
|
|
1041
|
-
console.log(`Found ${cycles.length} circular dependencies:\n`);
|
|
1042
|
-
for (const c of cycles) {
|
|
1043
|
-
console.log(`🔴 Cycle (${c.length} nodes): ${c.cycle.join(' → ')}`);
|
|
1044
|
-
console.log(` Break at: ${c.breakPoint}`);
|
|
1045
|
-
}
|
|
1046
|
-
const stats = detector.getStats(cycles);
|
|
1047
|
-
console.log(`\nStats: ${stats.totalCycles} cycles, max length ${stats.maxLength}, avg ${stats.avgLength}`);
|
|
1048
|
-
});
|
|
1049
|
-
program
|
|
1050
|
-
.command('dupes')
|
|
1051
|
-
.description('Detect code duplication')
|
|
1052
|
-
.option('-f, --files <json>', 'Files as JSON {filepath: code}')
|
|
1053
|
-
.action((options) => {
|
|
1054
|
-
if (!options.files) {
|
|
1055
|
-
console.log('❌ Provide --files as JSON');
|
|
1056
|
-
return;
|
|
1057
|
-
}
|
|
1058
|
-
const detector = new index_1.DuplicationDetector();
|
|
1059
|
-
const files = JSON.parse(options.files);
|
|
1060
|
-
const groups = detector.detectClones(files);
|
|
1061
|
-
if (groups.length === 0) {
|
|
1062
|
-
console.log('✅ No code duplication detected.');
|
|
1063
|
-
return;
|
|
1064
|
-
}
|
|
1065
|
-
console.log(`Found ${groups.length} duplication groups:\n`);
|
|
1066
|
-
for (const g of groups.slice(0, 5)) {
|
|
1067
|
-
console.log(`📋 Group ${g.id} (${(g.similarity * 100).toFixed(0)}% similar)`);
|
|
1068
|
-
console.log(` Files: ${g.files.join(', ')}`);
|
|
1069
|
-
console.log(` ${detector.getExtractHelperAction(g)}`);
|
|
1070
|
-
}
|
|
1071
|
-
const stats = detector.getStats(groups);
|
|
1072
|
-
console.log(`\nStats: ${stats.totalGroups} groups across ${stats.totalFiles} files, avg similarity ${stats.avgSimilarity}`);
|
|
1073
|
-
});
|
|
1074
|
-
program
|
|
1075
|
-
.command('complexity')
|
|
1076
|
-
.description('Analyze code complexity')
|
|
1077
|
-
.option('-c, --code <code>', 'Code to analyze')
|
|
1078
|
-
.option('-f, --file <name>', 'File name')
|
|
1079
|
-
.action((options) => {
|
|
1080
|
-
if (!options.code || !options.file) {
|
|
1081
|
-
console.log('❌ Provide --code and --file');
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
1084
|
-
const analyzer = new index_1.ComplexityAnalyzer();
|
|
1085
|
-
const reports = analyzer.analyze(options.code, options.file);
|
|
1086
|
-
if (reports.length === 0) {
|
|
1087
|
-
console.log('✅ No functions found.');
|
|
1088
|
-
return;
|
|
1089
|
-
}
|
|
1090
|
-
const hotspots = analyzer.getHotspots(reports);
|
|
1091
|
-
console.log(`${reports.length} functions analyzed. ${hotspots.length} hotspots:\n`);
|
|
1092
|
-
for (const r of hotspots) {
|
|
1093
|
-
const icon = r.level === 'high' ? '🔴' : '🟡';
|
|
1094
|
-
console.log(`${icon} ${r.function} (complexity: ${r.complexity}, ${r.level})`);
|
|
1095
|
-
console.log(` ${r.file}:${r.line}`);
|
|
1096
|
-
console.log(` ${r.suggestion}`);
|
|
1097
|
-
console.log('');
|
|
1098
|
-
}
|
|
1099
|
-
const stats = analyzer.getStats(reports);
|
|
1100
|
-
console.log(`Stats: ${stats.total} functions, ${stats.high} high, ${stats.medium} medium, ${stats.low} low, avg ${stats.avgComplexity}`);
|
|
1101
|
-
});
|
|
1102
|
-
program
|
|
1103
|
-
.command('deps')
|
|
1104
|
-
.description('Check dependency health')
|
|
1105
|
-
.option('-d, --deps <json>', 'Dependencies as JSON {name: version}')
|
|
1106
|
-
.option('-l, --latest <json>', 'Latest versions as JSON {name: version}')
|
|
1107
|
-
.action((options) => {
|
|
1108
|
-
if (!options.deps || !options.latest) {
|
|
1109
|
-
console.log('❌ Provide --deps and --latest as JSON');
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
|
-
const checker = new index_1.DependencyHealthChecker();
|
|
1113
|
-
const deps = JSON.parse(options.deps);
|
|
1114
|
-
const latest = JSON.parse(options.latest);
|
|
1115
|
-
const reports = checker.check(deps, latest);
|
|
1116
|
-
console.log(`${reports.length} dependencies checked:\n`);
|
|
1117
|
-
for (const r of reports) {
|
|
1118
|
-
const icons = { up_to_date: '✅', minor_behind: '🟡', major_behind: '🟠', deprecated: '🔴' };
|
|
1119
|
-
console.log(`${icons[r.status]} ${r.name}: ${r.current} → ${r.latest} ${r.breakingChanges ? '(BREAKING)' : ''}`);
|
|
1120
|
-
}
|
|
1121
|
-
console.log(`\n${checker.getFullUpdatePlan(reports)}`);
|
|
1122
|
-
const stats = checker.getStats(reports);
|
|
1123
|
-
console.log(`Stats: ${stats.total} total, ${stats.outdated} outdated, ${stats.deprecated} deprecated, ${stats.upToDate} up-to-date`);
|
|
1124
|
-
});
|
|
1125
|
-
program
|
|
1126
|
-
.command('abtest')
|
|
1127
|
-
.description('Run A/B test')
|
|
1128
|
-
.option('-n, --name <name>', 'Test name')
|
|
1129
|
-
.option('-c, --control <n>', 'Control group size', '10')
|
|
1130
|
-
.option('-e, --experiment <n>', 'Experiment group size', '10')
|
|
1131
|
-
.option('-t, --test-id <id>', 'Test ID for recording predictions')
|
|
1132
|
-
.option('-p, --prediction <id>', 'Prediction ID')
|
|
1133
|
-
.option('-g, --group <group>', 'Group: control or experiment')
|
|
1134
|
-
.option('-w, --was-correct', 'Was the prediction correct?')
|
|
1135
|
-
.option('--significance', 'Check statistical significance')
|
|
1136
|
-
.action((options) => {
|
|
1137
|
-
const framework = new index_1.ABTestFramework();
|
|
1138
|
-
if (options.name) {
|
|
1139
|
-
const test = framework.createTest(options.name, parseInt(options.control), parseInt(options.experiment));
|
|
1140
|
-
console.log(`✅ A/B test created: ${test.id}`);
|
|
1141
|
-
console.log(` Control: ${test.controlGroup.length}, Experiment: ${test.experimentGroup.length}`);
|
|
1142
|
-
return;
|
|
1143
|
-
}
|
|
1144
|
-
if (options.testId && options.prediction && options.group) {
|
|
1145
|
-
framework.recordPrediction(options.testId, options.prediction, options.wasCorrect || false, options.group);
|
|
1146
|
-
const stats = framework.getStats(options.testId);
|
|
1147
|
-
console.log(`📊 Test ${options.testId}:`);
|
|
1148
|
-
console.log(` Control accuracy: ${stats.controlAccuracy}`);
|
|
1149
|
-
console.log(` Experiment accuracy: ${stats.experimentAccuracy}`);
|
|
1150
|
-
console.log(` Total predictions: ${stats.totalPredictions}`);
|
|
1151
|
-
return;
|
|
1152
|
-
}
|
|
1153
|
-
if (options.significance && options.testId) {
|
|
1154
|
-
const result = framework.computeSignificance(options.testId);
|
|
1155
|
-
console.log(`📊 Significance test for ${options.testId}:`);
|
|
1156
|
-
console.log(` p-value: ${result.pValue}`);
|
|
1157
|
-
console.log(` Significant: ${result.isSignificant ? 'YES' : 'NO'}`);
|
|
1158
|
-
console.log(` Winner: ${result.winner}`);
|
|
1159
|
-
return;
|
|
1160
|
-
}
|
|
1161
|
-
const tests = framework.getAllTests();
|
|
1162
|
-
console.log(`${tests.length} A/B tests:`);
|
|
1163
|
-
for (const t of tests) {
|
|
1164
|
-
console.log(` ${t.id}: ${t.name} (${t.predictions.length} predictions)`);
|
|
1165
|
-
}
|
|
1166
|
-
});
|
|
1167
|
-
program
|
|
1168
|
-
.command('community-live')
|
|
1169
|
-
.description('Show live community prior stats')
|
|
1170
|
-
.option('--ingest <json>', 'Ingest signals JSON')
|
|
1171
|
-
.option('--decay', 'Apply faster decay to synthetic patterns')
|
|
1172
|
-
.option('--opt-out <user>', 'Opt out of community contribution')
|
|
1173
|
-
.option('--opt-in <user>', 'Opt back into community contribution')
|
|
1174
|
-
.action((options) => {
|
|
1175
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
1176
|
-
const live = new index_1.CommunityLive(cellDir);
|
|
1177
|
-
if (options.ingest) {
|
|
1178
|
-
const signals = JSON.parse(options.ingest);
|
|
1179
|
-
const stats = live.ingestSignals(signals);
|
|
1180
|
-
console.log(`📥 Ingested: ${stats.totalIngested} total, ${stats.syntheticReplaced} synthetic→live`);
|
|
1181
|
-
console.log(` Remaining synthetic: ${stats.remainingSynthetic}`);
|
|
1182
|
-
console.log(` Weekly rate: ${stats.weeklyRate}`);
|
|
1183
|
-
return;
|
|
1184
|
-
}
|
|
1185
|
-
if (options.decay) {
|
|
1186
|
-
live.applyFasterDecay();
|
|
1187
|
-
console.log('✅ Faster decay applied to synthetic patterns.');
|
|
1188
|
-
return;
|
|
1189
|
-
}
|
|
1190
|
-
if (options.optOut) {
|
|
1191
|
-
live.optOut(options.optOut);
|
|
1192
|
-
console.log(`✅ ${options.optOut} opted out of community contribution.`);
|
|
1193
|
-
return;
|
|
1194
|
-
}
|
|
1195
|
-
if (options.optIn) {
|
|
1196
|
-
live.optIn(options.optIn);
|
|
1197
|
-
console.log(`✅ ${options.optIn} opted back into community contribution.`);
|
|
1198
|
-
return;
|
|
1199
|
-
}
|
|
1200
|
-
const stats = live.getStats();
|
|
1201
|
-
console.log(`\n🌍 ${live.getDisplayLabel()}`);
|
|
1202
|
-
console.log(` Total ingested: ${stats.totalIngested}`);
|
|
1203
|
-
console.log(` Synthetic replaced: ${stats.syntheticReplaced}`);
|
|
1204
|
-
console.log(` Remaining synthetic: ${stats.remainingSynthetic}`);
|
|
1205
|
-
console.log(` Weekly rate: ${stats.weeklyRate}`);
|
|
1206
|
-
});
|
|
1207
|
-
program
|
|
1208
|
-
.command('community-full')
|
|
1209
|
-
.description('Show full community prior dashboard')
|
|
1210
|
-
.option('--translate <json>', 'Translate pattern across languages {pattern, from, to}')
|
|
1211
|
-
.action((options) => {
|
|
1212
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
1213
|
-
const full = new index_1.CommunityFull(cellDir);
|
|
1214
|
-
if (options.translate) {
|
|
1215
|
-
const { pattern, from, to } = JSON.parse(options.translate);
|
|
1216
|
-
const translated = full.translatePattern(pattern, from, to);
|
|
1217
|
-
if (translated) {
|
|
1218
|
-
console.log(`✅ Translated: ${translated.description} (confidence: ${translated.confidence.mean})`);
|
|
380
|
+
// ─── team pull ──────────────────────────────────────────────────────
|
|
381
|
+
if (sub === 'pull') {
|
|
382
|
+
console.log(C.primary(' Pulling team data...'));
|
|
383
|
+
const { teamPull } = require('./team-git');
|
|
384
|
+
const result = teamPull();
|
|
385
|
+
if (result.success) {
|
|
386
|
+
console.log(C.success(` ${result.message}`));
|
|
387
|
+
console.log(C.dim(` Members: ${result.newMembers}, Patterns: ${result.newPatterns}`));
|
|
1219
388
|
}
|
|
1220
389
|
else {
|
|
1221
|
-
console.log(
|
|
390
|
+
console.log(C.warn(` ${result.message}`));
|
|
1222
391
|
}
|
|
392
|
+
console.log();
|
|
1223
393
|
return;
|
|
1224
394
|
}
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
console.log(` Calibration: ${ds.calibrationPhase}`);
|
|
1233
|
-
console.log(` Cross-language maps: ${ds.crossLanguageMappings}`);
|
|
1234
|
-
console.log(`\n${full.getDisplayLabel()}`);
|
|
1235
|
-
const s = full.getStats();
|
|
1236
|
-
console.log(`\n All-real guarantee: ${s.isAllReal ? '✅ YES' : '❌ NO'}`);
|
|
1237
|
-
});
|
|
1238
|
-
program
|
|
1239
|
-
.command('xdomain')
|
|
1240
|
-
.description('Cross-domain projections (RESEARCH)')
|
|
1241
|
-
.option('-f, --from <domain>', 'Source domain')
|
|
1242
|
-
.option('-t, --to <domain>', 'Target domain')
|
|
1243
|
-
.option('--gate', 'Check research gate status')
|
|
1244
|
-
.action((options) => {
|
|
1245
|
-
const { CrossDomainProjections } = require('./core/cross-domain-projections');
|
|
1246
|
-
const projections = new CrossDomainProjections();
|
|
1247
|
-
if (options.gate) {
|
|
1248
|
-
console.log(projections.getResearchGateStatus());
|
|
1249
|
-
return;
|
|
1250
|
-
}
|
|
1251
|
-
if (options.from && options.to) {
|
|
1252
|
-
const proj = projections.getProjection(options.from, options.to);
|
|
1253
|
-
if (!proj) {
|
|
1254
|
-
console.log('❌ No projection available.');
|
|
395
|
+
// ─── team status ────────────────────────────────────────────────────
|
|
396
|
+
if (sub === 'status') {
|
|
397
|
+
const { teamStatus } = require('./team-git');
|
|
398
|
+
const intel = teamStatus();
|
|
399
|
+
if (!intel) {
|
|
400
|
+
console.log(C.dim(' No team data. Run: cell team push <your-name>'));
|
|
401
|
+
console.log();
|
|
1255
402
|
return;
|
|
1256
403
|
}
|
|
1257
|
-
console.log(
|
|
1258
|
-
console.log(`
|
|
1259
|
-
console.log(
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
404
|
+
console.log(C.bold(` Team: ${intel.summary.totalMembers} members`));
|
|
405
|
+
console.log(C.dim(` Patterns: ${intel.summary.totalPatterns}, Bus Factor: ${intel.summary.avgBusFactor}`));
|
|
406
|
+
console.log();
|
|
407
|
+
if (intel.members.length > 0) {
|
|
408
|
+
console.log(C.bold(' Members:'));
|
|
409
|
+
for (const m of intel.members) {
|
|
410
|
+
console.log(` ${C.success('•')} ${m.name} (${m.role}) — ${m.patterns} patterns`);
|
|
411
|
+
if (m.strengths.length > 0)
|
|
412
|
+
console.log(C.dim(` Strengths: ${m.strengths.join(', ')}`));
|
|
413
|
+
}
|
|
414
|
+
console.log();
|
|
1264
415
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
.
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
console.log(thick);
|
|
1287
|
-
console.log(C.primary.bold(centerText(`🔍 Search: "${query}"`)));
|
|
1288
|
-
console.log(thick);
|
|
1289
|
-
console.log();
|
|
1290
|
-
if (results.length === 0) {
|
|
1291
|
-
console.log(C.warn(centerText('No results found. Try different keywords.')));
|
|
416
|
+
if (intel.knowledgeMap.length > 0) {
|
|
417
|
+
console.log(C.bold(' Knowledge Map:'));
|
|
418
|
+
for (const k of intel.knowledgeMap) {
|
|
419
|
+
const risk = k.busFactor <= 1 ? C.warn('⚠ BUS=1') : C.dim(`bus=${k.busFactor}`);
|
|
420
|
+
console.log(` ${k.area}: ${k.experts.join(', ')} ${risk}`);
|
|
421
|
+
}
|
|
422
|
+
console.log();
|
|
423
|
+
}
|
|
424
|
+
if (intel.sharedPatterns.length > 0) {
|
|
425
|
+
console.log(C.bold(' Top Shared Patterns:'));
|
|
426
|
+
for (const p of intel.sharedPatterns.slice(0, 5)) {
|
|
427
|
+
console.log(` ${C.dim('•')} ${p.name}: ${p.value} (${p.count}x)`);
|
|
428
|
+
}
|
|
429
|
+
console.log();
|
|
430
|
+
}
|
|
431
|
+
if (intel.summary.strongestArea)
|
|
432
|
+
console.log(C.success(` + Strongest: ${intel.summary.strongestArea}`));
|
|
433
|
+
if (intel.summary.weakestArea)
|
|
434
|
+
console.log(C.warn(` ! Weakest: ${intel.summary.weakestArea}`));
|
|
435
|
+
if (intel.summary.criticalBlindSpots > 0)
|
|
436
|
+
console.log(C.warn(` ! ${intel.summary.criticalBlindSpots} critical blind spots`));
|
|
1292
437
|
console.log();
|
|
1293
|
-
console.log(thick);
|
|
1294
438
|
return;
|
|
1295
439
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
440
|
+
if (sub === 'add' && args[2]) {
|
|
441
|
+
const name = args[2];
|
|
442
|
+
const role = args[3] || 'developer';
|
|
443
|
+
db.prepare('INSERT INTO team_members (name, role) VALUES (?, ?)').run(name, role);
|
|
444
|
+
const members = db.prepare('SELECT name, role, joined_at FROM team_members').all();
|
|
445
|
+
(0, layers_1.saveTeamMembers)(members.map((m) => ({ name: m.name, role: m.role, joinedAt: m.joined_at })));
|
|
446
|
+
console.log(C.success(` Added: ${name} (${role})`));
|
|
447
|
+
console.log(C.dim(' Saved to .cell/team/members.json'));
|
|
1300
448
|
console.log();
|
|
1301
|
-
}
|
|
1302
|
-
console.log(C.dim(` ${results.length} results found`));
|
|
1303
|
-
console.log();
|
|
1304
|
-
console.log(thick);
|
|
1305
|
-
});
|
|
1306
|
-
// ─── TEAM ─────────────────────────────────────────────
|
|
1307
|
-
program
|
|
1308
|
-
.command('team')
|
|
1309
|
-
.description('Show team intelligence overview')
|
|
1310
|
-
.option('-o, --onboard', 'Generate onboarding document')
|
|
1311
|
-
.option('-a, --add-pattern <name>', 'Add team approved pattern')
|
|
1312
|
-
.option('-d, --desc <text>', 'Pattern description (with --add-pattern)')
|
|
1313
|
-
.option('-c, --category <cat>', 'Pattern category')
|
|
1314
|
-
.action((options) => {
|
|
1315
|
-
const te = new index_1.TeamEngine();
|
|
1316
|
-
if (options.addPattern && options.desc) {
|
|
1317
|
-
const cat = options.category || 'general';
|
|
1318
|
-
const r = te.addPattern(options.addPattern, options.desc, cat, 'local');
|
|
1319
|
-
console.log(C.success(`\n ✅ Team pattern added: ${r.id}`));
|
|
1320
|
-
console.log(C.dim(` "${options.addPattern}": ${options.desc}\n`));
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1323
|
-
if (options.onboard) {
|
|
1324
|
-
const doc = te.generateOnboarding();
|
|
1325
|
-
const outPath = path.join(process.cwd(), 'TEAM-ONBOARDING.md');
|
|
1326
|
-
fs.writeFileSync(outPath, doc, 'utf-8');
|
|
1327
|
-
console.log(C.success(`\n ✅ Onboarding doc generated: ${outPath}\n`));
|
|
1328
449
|
return;
|
|
1329
450
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
console.log(C.primary.bold(centerText('👥 Team Intelligence')));
|
|
1336
|
-
console.log(thick);
|
|
1337
|
-
console.log();
|
|
1338
|
-
if (summary.length === 0) {
|
|
1339
|
-
console.log(C.warn(centerText('No team data yet. Members push their taste with `cell push`.\nThen patterns and knowledge map will populate automatically.')));
|
|
451
|
+
if (sub === 'remove' && args[2]) {
|
|
452
|
+
db.prepare('DELETE FROM team_members WHERE name = ?').run(args[2]);
|
|
453
|
+
const members = db.prepare('SELECT name, role, joined_at FROM team_members').all();
|
|
454
|
+
(0, layers_1.saveTeamMembers)(members.map((m) => ({ name: m.name, role: m.role, joinedAt: m.joined_at })));
|
|
455
|
+
console.log(C.success(` Removed: ${args[2]}`));
|
|
1340
456
|
console.log();
|
|
1341
|
-
console.log(thick);
|
|
1342
457
|
return;
|
|
1343
458
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
console.log(C.dim(' cell team --onboard Generate onboarding doc'));
|
|
1349
|
-
console.log(C.dim(' cell team --add-pattern <name> --desc <text> Add pattern'));
|
|
1350
|
-
console.log(C.dim(' cell push Share your taste'));
|
|
1351
|
-
console.log(C.dim(' cell pull Pull team taste'));
|
|
1352
|
-
console.log(C.dim(' cell silos Check knowledge gaps'));
|
|
1353
|
-
console.log();
|
|
1354
|
-
console.log(thick);
|
|
1355
|
-
});
|
|
1356
|
-
// ─── PROOF ────────────────────────────────────────────
|
|
1357
|
-
program
|
|
1358
|
-
.command('proof')
|
|
1359
|
-
.description('Show evidence for every claim Cell makes')
|
|
1360
|
-
.action(() => {
|
|
1361
|
-
const proof = new index_1.ProofEngine();
|
|
1362
|
-
const report = proof.getReport();
|
|
1363
|
-
const summary = proof.getSummary();
|
|
1364
|
-
const thick = C.primary(hline('━'));
|
|
1365
|
-
const line = C.primaryDark(hline('─'));
|
|
1366
|
-
console.clear();
|
|
1367
|
-
console.log();
|
|
1368
|
-
console.log(thick);
|
|
1369
|
-
console.log(C.primary.bold(centerText('🔬 Proof System — Evidence For Every Claim')));
|
|
1370
|
-
console.log(thick);
|
|
1371
|
-
console.log();
|
|
1372
|
-
if (summary.length === 0 || summary[0].includes('Need more data')) {
|
|
1373
|
-
console.log(C.warn(centerText('Not enough data yet. Keep coding to build evidence.')));
|
|
459
|
+
// Default: show member list + team commands
|
|
460
|
+
const members = db.prepare('SELECT name, role, joined_at FROM team_members').all();
|
|
461
|
+
if (members.length === 0) {
|
|
462
|
+
console.log(C.dim(' No team members yet.'));
|
|
1374
463
|
console.log();
|
|
1375
|
-
console.log(C.info(' Cell needs 3+ occurrences of each pattern before it can prove claims.'));
|
|
1376
|
-
console.log(C.info(' cell watch chalu rakho — evidence auto-build hoga.'));
|
|
1377
464
|
}
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
465
|
+
console.log(C.bold(' Members:'));
|
|
466
|
+
for (const m of members) {
|
|
467
|
+
console.log(` ${C.num(m.name)} — ${m.role}`);
|
|
1381
468
|
}
|
|
1382
469
|
console.log();
|
|
1383
|
-
console.log(
|
|
470
|
+
console.log(' Commands:');
|
|
471
|
+
console.log(` ${C.primary('cell team push <name>')} Share your patterns with team`);
|
|
472
|
+
console.log(` ${C.primary('cell team pull')} Pull team data from git`);
|
|
473
|
+
console.log(` ${C.primary('cell team status')} Team intelligence dashboard`);
|
|
474
|
+
console.log(` ${C.primary('cell team add/remove')} Manage members`);
|
|
1384
475
|
console.log();
|
|
1385
|
-
}
|
|
1386
|
-
// ───
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
.
|
|
1390
|
-
.
|
|
1391
|
-
.
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
const { startDaemon } = await Promise.resolve().then(() => __importStar(require('./daemon/lifecycle')));
|
|
1395
|
-
const result = await startDaemon();
|
|
1396
|
-
console.log(`✅ Daemon started (PID: ${result.pid}, Port: ${result.port})`);
|
|
1397
|
-
console.log(` Health: http://localhost:${result.port}/health`);
|
|
1398
|
-
}
|
|
1399
|
-
catch (err) {
|
|
1400
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1401
|
-
console.error(`❌ Failed to start daemon: ${message}`);
|
|
1402
|
-
}
|
|
1403
|
-
});
|
|
1404
|
-
daemonCmd
|
|
1405
|
-
.command('stop')
|
|
1406
|
-
.description('Stop the Cell Daemon')
|
|
1407
|
-
.action(async () => {
|
|
1408
|
-
const { stopDaemon } = await Promise.resolve().then(() => __importStar(require('./daemon/lifecycle')));
|
|
1409
|
-
const result = stopDaemon();
|
|
1410
|
-
console.log(result.success ? `✅ ${result.message}` : `⚠️ ${result.message}`);
|
|
1411
|
-
});
|
|
1412
|
-
daemonCmd
|
|
1413
|
-
.command('restart')
|
|
1414
|
-
.description('Restart the Cell Daemon')
|
|
1415
|
-
.action(async () => {
|
|
1416
|
-
console.log('Restarting Cell Daemon...');
|
|
1417
|
-
try {
|
|
1418
|
-
const { restartDaemon } = await Promise.resolve().then(() => __importStar(require('./daemon/lifecycle')));
|
|
1419
|
-
const result = await restartDaemon();
|
|
1420
|
-
console.log(`✅ Daemon restarted (PID: ${result.pid}, Port: ${result.port})`);
|
|
1421
|
-
}
|
|
1422
|
-
catch (err) {
|
|
1423
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1424
|
-
console.error(`❌ Failed to restart daemon: ${message}`);
|
|
1425
|
-
}
|
|
1426
|
-
});
|
|
1427
|
-
daemonCmd
|
|
1428
|
-
.command('status')
|
|
1429
|
-
.description('Show daemon status')
|
|
1430
|
-
.action(async () => {
|
|
1431
|
-
const { statusDaemon } = await Promise.resolve().then(() => __importStar(require('./daemon/lifecycle')));
|
|
1432
|
-
const status = await statusDaemon();
|
|
1433
|
-
if (status.running && status.health) {
|
|
1434
|
-
const h = status.health;
|
|
1435
|
-
console.log('✅ Daemon is running');
|
|
1436
|
-
console.log(` PID: ${status.pid} | Port: ${status.port}`);
|
|
1437
|
-
console.log(` Uptime: ${Math.round(h.uptime)}s | Patterns: ${h.patterns} | Signals: ${h.signals}`);
|
|
1438
|
-
console.log(` Modules: ${h.modulesLoaded || 'N/A'} | Memory: ${Math.round(h.memory / 1024 / 1024)}MB`);
|
|
1439
|
-
}
|
|
1440
|
-
else {
|
|
1441
|
-
console.log('❌ Daemon is not running');
|
|
1442
|
-
if (status.pid)
|
|
1443
|
-
console.log(` Stale PID found: ${status.pid}`);
|
|
1444
|
-
}
|
|
1445
|
-
});
|
|
1446
|
-
// ─── Top-level start/stop shortcuts ────────────────────
|
|
1447
|
-
program
|
|
1448
|
-
.command('start')
|
|
1449
|
-
.description('Start the Cell Daemon + auto-learn file watcher')
|
|
1450
|
-
.action(async () => {
|
|
1451
|
-
console.log(C.primary('Starting Cell Daemon...'));
|
|
1452
|
-
try {
|
|
1453
|
-
const { startDaemon } = await Promise.resolve().then(() => __importStar(require('./daemon/lifecycle')));
|
|
1454
|
-
const result = await startDaemon();
|
|
1455
|
-
console.log(C.success(`✅ Daemon started (PID: ${result.pid}, Port: ${result.port})`));
|
|
1456
|
-
console.log(C.info(` Health: http://localhost:${result.port}/health`));
|
|
1457
|
-
// Auto-start file watcher in background
|
|
476
|
+
}
|
|
477
|
+
// ─── cell community ─────────────────────────────────────────────────────────
|
|
478
|
+
function doCommunity() {
|
|
479
|
+
console.log();
|
|
480
|
+
console.log(C.bold(' Cell Community'));
|
|
481
|
+
console.log(C.dim(' ──────────────'));
|
|
482
|
+
console.log();
|
|
483
|
+
const sub = args[1] || '';
|
|
484
|
+
if (sub === 'share') {
|
|
1458
485
|
try {
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
cwd: process.cwd(),
|
|
1464
|
-
}).unref();
|
|
1465
|
-
console.log(C.accent('\n👁️ Auto-Learn: Watching files for changes...'));
|
|
1466
|
-
console.log(C.dim(' Edit any source file → Cell learns automatically'));
|
|
486
|
+
const { sharePatterns } = require('./community-intel');
|
|
487
|
+
const result = sharePatterns();
|
|
488
|
+
console.log(result.success ? C.success(` ${result.message}`) : C.warn(` ${result.message}`));
|
|
489
|
+
console.log(C.dim(' Anonymous — only pattern types shared, zero code.'));
|
|
1467
490
|
}
|
|
1468
491
|
catch {
|
|
1469
|
-
console.log(C.
|
|
492
|
+
console.log(C.warn(' Share failed. Run cell scan first.'));
|
|
1470
493
|
}
|
|
1471
|
-
console.log(
|
|
1472
|
-
|
|
1473
|
-
catch (err) {
|
|
1474
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
1475
|
-
console.error(C.error(`❌ Failed to start daemon: ${message}`));
|
|
1476
|
-
}
|
|
1477
|
-
});
|
|
1478
|
-
program
|
|
1479
|
-
.command('stop')
|
|
1480
|
-
.description('Stop the Cell Daemon')
|
|
1481
|
-
.action(async () => {
|
|
1482
|
-
const { stopDaemon } = await Promise.resolve().then(() => __importStar(require('./daemon/lifecycle')));
|
|
1483
|
-
const result = stopDaemon();
|
|
1484
|
-
console.log(result.success ? C.success(`✅ ${result.message}`) : C.warn(`⚠️ ${result.message}`));
|
|
1485
|
-
});
|
|
1486
|
-
program
|
|
1487
|
-
.command('cloud')
|
|
1488
|
-
.description('Manage cloud sync')
|
|
1489
|
-
.addCommand(new commander_1.Command('on')
|
|
1490
|
-
.description('Enable cloud sync (anonymous pattern stats only)')
|
|
1491
|
-
.action(() => {
|
|
1492
|
-
const cellDir = path.join(os.homedir(), '.fivo', 'cell');
|
|
1493
|
-
if (!fs.existsSync(cellDir))
|
|
1494
|
-
fs.mkdirSync(cellDir, { recursive: true });
|
|
1495
|
-
const configPath = path.join(cellDir, 'cell-meta.json');
|
|
1496
|
-
let meta = {};
|
|
1497
|
-
if (fs.existsSync(configPath))
|
|
1498
|
-
meta = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
1499
|
-
meta.cloudSyncEnabled = true;
|
|
1500
|
-
fs.writeFileSync(configPath, JSON.stringify(meta, null, 2), 'utf-8');
|
|
1501
|
-
console.log('🌐 Cloud sync: ON');
|
|
1502
|
-
console.log(' Anonymous pattern stats shared. Code NEVER leaves your machine.');
|
|
1503
|
-
console.log(' Turn off: cell cloud off');
|
|
1504
|
-
}))
|
|
1505
|
-
.addCommand(new commander_1.Command('off')
|
|
1506
|
-
.description('Disable cloud sync (fully offline)')
|
|
1507
|
-
.action(() => {
|
|
1508
|
-
const cellDir = path.join(os.homedir(), '.fivo', 'cell');
|
|
1509
|
-
if (!fs.existsSync(cellDir))
|
|
1510
|
-
fs.mkdirSync(cellDir, { recursive: true });
|
|
1511
|
-
const configPath = path.join(cellDir, 'cell-meta.json');
|
|
1512
|
-
let meta = {};
|
|
1513
|
-
if (fs.existsSync(configPath))
|
|
1514
|
-
meta = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
1515
|
-
meta.cloudSyncEnabled = false;
|
|
1516
|
-
fs.writeFileSync(configPath, JSON.stringify(meta, null, 2), 'utf-8');
|
|
1517
|
-
console.log('🔒 Cloud sync: OFF');
|
|
1518
|
-
console.log(' Fully offline. Nothing leaves your machine.');
|
|
1519
|
-
console.log(' Turn on: cell cloud on');
|
|
1520
|
-
}));
|
|
1521
|
-
program
|
|
1522
|
-
.command('privacy')
|
|
1523
|
-
.description('Show privacy settings and current sharing status')
|
|
1524
|
-
.action(async () => {
|
|
1525
|
-
const http = await Promise.resolve().then(() => __importStar(require('http')));
|
|
1526
|
-
return new Promise((resolve) => {
|
|
1527
|
-
http.get('http://localhost:9876/privacy/mode', (res) => {
|
|
1528
|
-
let data = '';
|
|
1529
|
-
res.on('data', (chunk) => data += chunk);
|
|
1530
|
-
res.on('end', () => {
|
|
1531
|
-
try {
|
|
1532
|
-
const { mode } = JSON.parse(data);
|
|
1533
|
-
console.log(`\n🔒 Privacy Mode: ${mode}`);
|
|
1534
|
-
console.log(` Change: cell cloud on (community) | cell cloud off (private)\n`);
|
|
1535
|
-
}
|
|
1536
|
-
catch {
|
|
1537
|
-
console.log('\n🔒 Privacy Mode: private (daemon not reachable, showing default)\n');
|
|
1538
|
-
}
|
|
1539
|
-
resolve();
|
|
1540
|
-
});
|
|
1541
|
-
}).on('error', () => {
|
|
1542
|
-
console.log('\n🔒 Privacy Mode: private (daemon not reachable, showing default)\n');
|
|
1543
|
-
resolve();
|
|
1544
|
-
});
|
|
1545
|
-
});
|
|
1546
|
-
});
|
|
1547
|
-
// ─── Auto-Learn: File Watcher ──────────────────────────
|
|
1548
|
-
program
|
|
1549
|
-
.command('watch')
|
|
1550
|
-
.description('Watch files and learn automatically from every edit')
|
|
1551
|
-
.action(() => {
|
|
1552
|
-
const cellDir = path.join(process.cwd(), index_1.DEFAULT_CONFIG.cellDir);
|
|
1553
|
-
if (!fs.existsSync(cellDir)) {
|
|
1554
|
-
fs.mkdirSync(cellDir, { recursive: true });
|
|
1555
|
-
const store = new index_1.PatternStore(cellDir);
|
|
1556
|
-
store.save();
|
|
1557
|
-
}
|
|
1558
|
-
const store = new index_1.PatternStore(cellDir);
|
|
1559
|
-
const cellStore = new index_1.CellStore();
|
|
1560
|
-
const capture = new index_1.SignalCapture();
|
|
1561
|
-
const cascade = new index_1.ExtractionCascade();
|
|
1562
|
-
const cellDir2 = path.join(process.cwd(), '.cell');
|
|
1563
|
-
const blindSpots = new index_1.BlindSpotEngine(cellDir);
|
|
1564
|
-
const naming = new index_1.NamingEngine(cellDir2);
|
|
1565
|
-
const structure = new index_1.StructureEngine(cellDir2);
|
|
1566
|
-
const frontend = new index_1.FrontendEngine(cellDir2);
|
|
1567
|
-
const backend = new index_1.BackendEngine(cellDir2);
|
|
1568
|
-
const productivity = new index_1.ProductivityEngine(cellDir2);
|
|
1569
|
-
const syntax = new index_1.SyntaxEngine(cellDir2);
|
|
1570
|
-
const arch = new index_1.ArchitectureEngine(cellDir2);
|
|
1571
|
-
const knowledge = new index_1.KnowledgeGraphEngine(cellDir2);
|
|
1572
|
-
const proof = new index_1.ProofEngine(cellDir2);
|
|
1573
|
-
const filePrevMap = new Map();
|
|
1574
|
-
const timers = {};
|
|
1575
|
-
let learned = 0;
|
|
1576
|
-
function getLang(fp) {
|
|
1577
|
-
const ext = path.extname(fp).toLowerCase();
|
|
1578
|
-
const m = {
|
|
1579
|
-
'.ts': 'typescript', '.tsx': 'typescript', '.js': 'javascript', '.jsx': 'javascript',
|
|
1580
|
-
'.py': 'python', '.go': 'go', '.java': 'java', '.rb': 'ruby', '.rs': 'rust',
|
|
1581
|
-
'.cs': 'csharp', '.php': 'php', '.swift': 'swift', '.kt': 'kotlin',
|
|
1582
|
-
};
|
|
1583
|
-
return m[ext] || 'unknown';
|
|
494
|
+
console.log();
|
|
495
|
+
return;
|
|
1584
496
|
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
const
|
|
1592
|
-
|
|
1593
|
-
fileVersions.set(filePath, current);
|
|
1594
|
-
if (!previous || previous === current)
|
|
1595
|
-
return;
|
|
1596
|
-
const lang = getLang(filePath);
|
|
1597
|
-
const ctx = {
|
|
1598
|
-
language: lang,
|
|
1599
|
-
framework: 'unknown',
|
|
1600
|
-
fileType: path.extname(filePath),
|
|
1601
|
-
strictness: 'moderate',
|
|
1602
|
-
projectId: path.basename(process.cwd()),
|
|
1603
|
-
};
|
|
1604
|
-
capture.captureEditDiff(previous, current, ctx);
|
|
1605
|
-
const result = cascade.extract(previous, current, lang);
|
|
1606
|
-
const spots = blindSpots.analyze(current, lang);
|
|
1607
|
-
naming.analyze(current);
|
|
1608
|
-
structure.analyze(current);
|
|
1609
|
-
frontend.analyze(current);
|
|
1610
|
-
backend.analyze(current);
|
|
1611
|
-
syntax.analyze(current);
|
|
1612
|
-
arch.analyze(current, rel);
|
|
1613
|
-
knowledge.detectTechnologies(current, rel);
|
|
1614
|
-
knowledge.updateSession(rel, 'edited');
|
|
1615
|
-
productivity.analyzeEngineering(current, rel);
|
|
1616
|
-
if (previous)
|
|
1617
|
-
productivity.recordEdit(previous, current);
|
|
1618
|
-
for (const p of result.patterns) {
|
|
1619
|
-
store.addOrUpdatePattern(p.category, p.description, p.from, p.to, true, p.conditions, 'global', result.stepUsed, lang);
|
|
1620
|
-
}
|
|
1621
|
-
store.save();
|
|
1622
|
-
try {
|
|
1623
|
-
cellStore.syncFromPatternStore(store);
|
|
497
|
+
if (sub === 'browse' || sub === '') {
|
|
498
|
+
try {
|
|
499
|
+
const { generateCommunityReport } = require('./community-intel');
|
|
500
|
+
const report = generateCommunityReport();
|
|
501
|
+
if (report.patterns.length > 0) {
|
|
502
|
+
console.log(C.bold(` 📊 Top Patterns (${report.patterns.length} total):`));
|
|
503
|
+
for (const p of report.patterns.slice(0, 8)) {
|
|
504
|
+
console.log(` ${C.num(String(p.percentage))}% ${p.category}: ${p.description}`);
|
|
1624
505
|
}
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
proof.verifyPrediction(s.description, s.hitRate > 0.3);
|
|
506
|
+
console.log();
|
|
507
|
+
}
|
|
508
|
+
if (report.benchmarks.length > 0) {
|
|
509
|
+
console.log(C.bold(' 📈 Benchmarks:'));
|
|
510
|
+
for (const b of report.benchmarks) {
|
|
511
|
+
console.log(` ${b.metric}: ${C.num(String(b.percentile))}th percentile — ${b.interpretation}`);
|
|
1632
512
|
}
|
|
1633
|
-
|
|
1634
|
-
learned += result.patterns.length;
|
|
1635
|
-
const parts = [];
|
|
1636
|
-
if (result.patterns.length > 0)
|
|
1637
|
-
parts.push(C.success(`${result.patterns.length}p`));
|
|
1638
|
-
if (spots.length > 0)
|
|
1639
|
-
parts.push(C.warn(`${spots.length} blind spots`));
|
|
1640
|
-
console.log(C.success(` 📝 ${rel}`) + C.dim(` → ${parts.join(', ')} (total: ${learned})`));
|
|
513
|
+
console.log();
|
|
1641
514
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
try {
|
|
1647
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1648
|
-
for (const e of entries) {
|
|
1649
|
-
const full = path.join(dir, e.name);
|
|
1650
|
-
if (e.isDirectory() && !['node_modules', '.fivo', '.git', 'dist', 'coverage', '.next', '.cache'].includes(e.name)) {
|
|
1651
|
-
watchDir(full);
|
|
1652
|
-
// Watch directory for new files
|
|
1653
|
-
try {
|
|
1654
|
-
fs.watch(full, (ev) => {
|
|
1655
|
-
if (ev === 'rename') {
|
|
1656
|
-
setTimeout(() => {
|
|
1657
|
-
try {
|
|
1658
|
-
const newEntries = fs.readdirSync(full, { withFileTypes: true });
|
|
1659
|
-
for (const ne of newEntries) {
|
|
1660
|
-
const nf = path.join(full, ne.name);
|
|
1661
|
-
if (ne.isFile() && /\.(ts|tsx|js|jsx|py|go|java|rb|rs|cs|php|swift|kt)$/.test(ne.name)) {
|
|
1662
|
-
if (!fileVersions.has(nf)) {
|
|
1663
|
-
fileVersions.set(nf, fs.readFileSync(nf, 'utf-8'));
|
|
1664
|
-
console.log(C.dim(` 📄 New file: ${path.relative(process.cwd(), nf)}`));
|
|
1665
|
-
}
|
|
1666
|
-
fs.watch(nf, (ev2) => { if (ev2 === 'change')
|
|
1667
|
-
processFile(nf); });
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
catch { }
|
|
1672
|
-
}, 200);
|
|
1673
|
-
}
|
|
1674
|
-
});
|
|
1675
|
-
}
|
|
1676
|
-
catch { }
|
|
515
|
+
if (report.topStacks.length > 0) {
|
|
516
|
+
console.log(C.bold(' 🏗️ Top Stacks:'));
|
|
517
|
+
for (const s of report.topStacks) {
|
|
518
|
+
console.log(` ${C.success('•')} ${s.stack} (${s.count}x)`);
|
|
1677
519
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
}
|
|
1685
|
-
fs.watch(full, (ev) => { if (ev === 'change')
|
|
1686
|
-
processFile(full); });
|
|
520
|
+
console.log();
|
|
521
|
+
}
|
|
522
|
+
if (report.topBlindSpots.length > 0) {
|
|
523
|
+
console.log(C.bold(' ⚠️ Common Blind Spots:'));
|
|
524
|
+
for (const b of report.topBlindSpots) {
|
|
525
|
+
console.log(` ${C.warn('!')} ${b.blindSpot} (${b.percentage}%)`);
|
|
1687
526
|
}
|
|
527
|
+
console.log();
|
|
1688
528
|
}
|
|
1689
529
|
}
|
|
1690
|
-
catch {
|
|
530
|
+
catch {
|
|
531
|
+
console.log(C.dim(' No community data yet. Run: cell scan first.'));
|
|
532
|
+
}
|
|
533
|
+
return;
|
|
1691
534
|
}
|
|
1692
|
-
|
|
1693
|
-
console.
|
|
535
|
+
console.log(' Commands:');
|
|
536
|
+
console.log(' cell community browse Browse community patterns & benchmarks');
|
|
537
|
+
console.log(' cell community share Share patterns anonymously');
|
|
1694
538
|
console.log();
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
539
|
+
}
|
|
540
|
+
// ─── cell help ──────────────────────────────────────────────────────────────
|
|
541
|
+
function doHelp() {
|
|
1698
542
|
console.log();
|
|
1699
|
-
console.log(C.
|
|
1700
|
-
console.log(C.dim('
|
|
1701
|
-
console.log(C.dim(' Press Ctrl+C to stop'));
|
|
543
|
+
console.log(C.bold(' Cell Commands'));
|
|
544
|
+
console.log(C.dim(' ─────────────'));
|
|
1702
545
|
console.log();
|
|
1703
|
-
console.log(
|
|
546
|
+
console.log(` ${C.primary('cell start')} Start daemon + MCP (port 9876)`);
|
|
547
|
+
console.log(` ${C.primary('cell stop')} Stop daemon`);
|
|
548
|
+
console.log(` ${C.primary('cell scan')} Scan codebase + build layers`);
|
|
549
|
+
console.log(` ${C.primary('cell status')} What Cell knows about you`);
|
|
550
|
+
console.log(` ${C.primary('cell team')} Team collaboration (git-based)`);
|
|
551
|
+
console.log(` ${C.primary('cell community')} Community features`);
|
|
552
|
+
console.log(` ${C.primary('cell help')} Show this help`);
|
|
553
|
+
console.log();
|
|
554
|
+
console.log(C.dim(' Install: npm i -g fivocell'));
|
|
555
|
+
console.log(C.dim(' Then: cell start'));
|
|
1704
556
|
console.log();
|
|
1705
|
-
watchDir(process.cwd());
|
|
1706
|
-
});
|
|
1707
|
-
// ─── Auto-Learn: Git Hook ──────────────────────────────
|
|
1708
|
-
program
|
|
1709
|
-
.command('install-hook')
|
|
1710
|
-
.description('Install git hook for auto-learning on every commit')
|
|
1711
|
-
.action(() => {
|
|
1712
|
-
const gitDir = path.join(process.cwd(), '.git');
|
|
1713
|
-
if (!fs.existsSync(gitDir)) {
|
|
1714
|
-
console.log(C.error(' ❌ Not a git repository. Run `git init` first.'));
|
|
1715
|
-
return;
|
|
1716
|
-
}
|
|
1717
|
-
const hooksDir = path.join(gitDir, 'hooks');
|
|
1718
|
-
if (!fs.existsSync(hooksDir))
|
|
1719
|
-
fs.mkdirSync(hooksDir, { recursive: true });
|
|
1720
|
-
const hookPath = path.join(hooksDir, 'post-commit');
|
|
1721
|
-
const cellBin = process.argv[1];
|
|
1722
|
-
const hook = `#!/bin/sh
|
|
1723
|
-
# FIVO Cell — auto-learn on commit
|
|
1724
|
-
DIFF=$(git diff --cached --diff-algorithm=histogram)
|
|
1725
|
-
if [ -n "$DIFF" ]; then
|
|
1726
|
-
node "${cellBin}" learn --original "$(echo "$DIFF" | head -200)" --edited "committed" 2>/dev/null
|
|
1727
|
-
fi
|
|
1728
|
-
`;
|
|
1729
|
-
fs.writeFileSync(hookPath, hook, { mode: 0o755 });
|
|
1730
|
-
console.log(C.success('\n ✅ Git hook installed: post-commit'));
|
|
1731
|
-
console.log(C.info(' Every commit → Cell learns from the diff automatically.'));
|
|
1732
|
-
console.log(C.dim(' To remove: delete .git/hooks/post-commit\n'));
|
|
1733
|
-
});
|
|
1734
|
-
// ─── Auto-Start ───────────────────────────────────────
|
|
1735
|
-
program
|
|
1736
|
-
.command('autostart')
|
|
1737
|
-
.description('Auto-start Cell daemon on PC reboot')
|
|
1738
|
-
.addCommand(new commander_1.Command('on')
|
|
1739
|
-
.description('Enable auto-start on boot')
|
|
1740
|
-
.action(() => {
|
|
1741
|
-
const isWin = process.platform === 'win32';
|
|
1742
|
-
const cellCmd = process.argv[1];
|
|
1743
|
-
if (isWin) {
|
|
1744
|
-
const startupDir = path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
|
|
1745
|
-
if (!fs.existsSync(startupDir))
|
|
1746
|
-
fs.mkdirSync(startupDir, { recursive: true });
|
|
1747
|
-
const batPath = path.join(startupDir, 'fivo-cell-start.bat');
|
|
1748
|
-
fs.writeFileSync(batPath, `@echo off\r\n${cellCmd} start\r\n`, 'utf-8');
|
|
1749
|
-
console.log(C.success('\n ✅ Auto-start enabled (Windows)'));
|
|
1750
|
-
console.log(C.dim(` ${batPath}`));
|
|
1751
|
-
console.log(C.info(' PC reboot → Cell auto-starts\n'));
|
|
1752
|
-
}
|
|
1753
|
-
else {
|
|
1754
|
-
const bashrc = path.join(os.homedir(), '.bashrc');
|
|
1755
|
-
const line = `(cell status > /dev/null 2>&1) || ${cellCmd} start`;
|
|
1756
|
-
if (!fs.existsSync(bashrc))
|
|
1757
|
-
fs.writeFileSync(bashrc, '');
|
|
1758
|
-
const content = fs.readFileSync(bashrc, 'utf-8');
|
|
1759
|
-
if (!content.includes('cell start')) {
|
|
1760
|
-
fs.writeFileSync(bashrc, content + `\n# FIVO Cell auto-start\n${line}\n`);
|
|
1761
|
-
}
|
|
1762
|
-
console.log(C.success('\n ✅ Auto-start enabled (Linux/Mac)'));
|
|
1763
|
-
console.log(C.dim(` Added to ~/.bashrc`));
|
|
1764
|
-
console.log(C.info(' Terminal open → Cell auto-starts\n'));
|
|
1765
|
-
}
|
|
1766
|
-
}))
|
|
1767
|
-
.addCommand(new commander_1.Command('off')
|
|
1768
|
-
.description('Disable auto-start on boot')
|
|
1769
|
-
.action(() => {
|
|
1770
|
-
const isWin = process.platform === 'win32';
|
|
1771
|
-
if (isWin) {
|
|
1772
|
-
const startupDir = path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
|
|
1773
|
-
const batPath = path.join(startupDir, 'fivo-cell-start.bat');
|
|
1774
|
-
if (fs.existsSync(batPath))
|
|
1775
|
-
fs.unlinkSync(batPath);
|
|
1776
|
-
console.log(C.success('\n ✅ Auto-start disabled\n'));
|
|
1777
|
-
}
|
|
1778
|
-
else {
|
|
1779
|
-
const bashrc = path.join(os.homedir(), '.bashrc');
|
|
1780
|
-
if (fs.existsSync(bashrc)) {
|
|
1781
|
-
const content = fs.readFileSync(bashrc, 'utf-8')
|
|
1782
|
-
.replace(/\n# FIVO Cell auto-start\n.*\n?/, '\n')
|
|
1783
|
-
.trim();
|
|
1784
|
-
fs.writeFileSync(bashrc, content + '\n');
|
|
1785
|
-
}
|
|
1786
|
-
console.log(C.success('\n ✅ Auto-start disabled\n'));
|
|
1787
|
-
}
|
|
1788
|
-
}));
|
|
1789
|
-
// ─── Number Command Interception ──────────────────────
|
|
1790
|
-
const rawArgs = process.argv.slice(2);
|
|
1791
|
-
if (rawArgs.length === 0) {
|
|
1792
|
-
showBanner();
|
|
1793
|
-
process.exit(0);
|
|
1794
|
-
}
|
|
1795
|
-
const nums = parseNumberArg(rawArgs[0]);
|
|
1796
|
-
if (nums.length > 0) {
|
|
1797
|
-
runNumbers(nums);
|
|
1798
557
|
}
|
|
1799
|
-
program.parse(process.argv);
|
|
1800
558
|
//# sourceMappingURL=cli.js.map
|