fivocell 4.1.8 → 4.2.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agents-md.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-md.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/agents-md.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("fs"));
37
+ const os = __importStar(require("os"));
38
+ const path = __importStar(require("path"));
39
+ const agents_md_1 = require("../core/agents-md");
40
+ describe('agents-md (AGENTS.md + .cursorrules writers)', () => {
41
+ let tmpDir;
42
+ beforeEach(() => {
43
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cell-agents-md-'));
44
+ });
45
+ afterEach(() => {
46
+ try {
47
+ fs.rmSync(tmpDir, { recursive: true, force: true });
48
+ }
49
+ catch { }
50
+ });
51
+ describe('templates', () => {
52
+ it('AGENTS_MD_TEMPLATE declares FIVO Cell rules and the @cell convention', () => {
53
+ expect(agents_md_1.AGENTS_MD_TEMPLATE).toContain(agents_md_1.CELL_RULES_MARKER);
54
+ expect(agents_md_1.AGENTS_MD_TEMPLATE).toContain('@cell');
55
+ expect(agents_md_1.AGENTS_MD_TEMPLATE).toContain('cell_get_context');
56
+ expect(agents_md_1.AGENTS_MD_TEMPLATE).toContain('cell_session_start');
57
+ expect(agents_md_1.AGENTS_MD_TEMPLATE).toContain('path.basename(process.cwd())');
58
+ });
59
+ it('CURSORRULES_TEMPLATE mentions @cell and cell_get_context', () => {
60
+ expect(agents_md_1.CURSORRULES_TEMPLATE).toContain(agents_md_1.CELL_RULES_MARKER);
61
+ expect(agents_md_1.CURSORRULES_TEMPLATE).toContain('@cell');
62
+ expect(agents_md_1.CURSORRULES_TEMPLATE).toContain('cell_get_context');
63
+ });
64
+ it('isCellRulesFile detects the marker in any file content', () => {
65
+ expect((0, agents_md_1.isCellRulesFile)(agents_md_1.AGENTS_MD_TEMPLATE)).toBe(true);
66
+ expect((0, agents_md_1.isCellRulesFile)('# User custom rules')).toBe(false);
67
+ expect((0, agents_md_1.isCellRulesFile)('partial marker mention')).toBe(false);
68
+ expect((0, agents_md_1.isCellRulesFile)('# fivo-cell:rules:v1\n# body')).toBe(true);
69
+ });
70
+ });
71
+ describe('writeAgentsMd', () => {
72
+ it('writes AGENTS.md to project root', () => {
73
+ const result = (0, agents_md_1.writeAgentsMd)(tmpDir);
74
+ expect(result).toBe('written');
75
+ const filePath = path.join(tmpDir, agents_md_1.AGENTS_MD_FILENAME);
76
+ expect(fs.existsSync(filePath)).toBe(true);
77
+ const content = fs.readFileSync(filePath, 'utf8');
78
+ expect(content).toBe(agents_md_1.AGENTS_MD_TEMPLATE);
79
+ });
80
+ it('does not overwrite existing AGENTS.md (idempotent — respects user edits)', () => {
81
+ const filePath = path.join(tmpDir, agents_md_1.AGENTS_MD_FILENAME);
82
+ const custom = '# My custom team rules\nDo not touch this file.\n';
83
+ fs.writeFileSync(filePath, custom, 'utf8');
84
+ const result = (0, agents_md_1.writeAgentsMd)(tmpDir);
85
+ expect(result).toBe('exists');
86
+ const content = fs.readFileSync(filePath, 'utf8');
87
+ expect(content).toBe(custom);
88
+ });
89
+ it('overwrites existing AGENTS.md when overwrite: true', () => {
90
+ const filePath = path.join(tmpDir, agents_md_1.AGENTS_MD_FILENAME);
91
+ fs.writeFileSync(filePath, 'old content', 'utf8');
92
+ const result = (0, agents_md_1.writeAgentsMd)(tmpDir, { overwrite: true });
93
+ expect(result).toBe('written');
94
+ const content = fs.readFileSync(filePath, 'utf8');
95
+ expect(content).toBe(agents_md_1.AGENTS_MD_TEMPLATE);
96
+ });
97
+ });
98
+ describe('writeCursorRules', () => {
99
+ it('writes .cursorrules to project root', () => {
100
+ const result = (0, agents_md_1.writeCursorRules)(tmpDir);
101
+ expect(result).toBe('written');
102
+ const filePath = path.join(tmpDir, agents_md_1.CURSORRULES_FILENAME);
103
+ expect(fs.existsSync(filePath)).toBe(true);
104
+ });
105
+ it('does not overwrite existing .cursorrules', () => {
106
+ const filePath = path.join(tmpDir, agents_md_1.CURSORRULES_FILENAME);
107
+ fs.writeFileSync(filePath, 'user rules', 'utf8');
108
+ const result = (0, agents_md_1.writeCursorRules)(tmpDir);
109
+ expect(result).toBe('exists');
110
+ });
111
+ });
112
+ describe('writeCellRules', () => {
113
+ it('writes both files on a fresh project', () => {
114
+ const r = (0, agents_md_1.writeCellRules)(tmpDir);
115
+ expect(r.agentsMd).toBe('written');
116
+ expect(r.cursorRules).toBe('written');
117
+ expect(fs.existsSync(path.join(tmpDir, agents_md_1.AGENTS_MD_FILENAME))).toBe(true);
118
+ expect(fs.existsSync(path.join(tmpDir, agents_md_1.CURSORRULES_FILENAME))).toBe(true);
119
+ });
120
+ it('returns exists for both when both files already present', () => {
121
+ fs.writeFileSync(path.join(tmpDir, agents_md_1.AGENTS_MD_FILENAME), 'x', 'utf8');
122
+ fs.writeFileSync(path.join(tmpDir, agents_md_1.CURSORRULES_FILENAME), 'y', 'utf8');
123
+ const r = (0, agents_md_1.writeCellRules)(tmpDir);
124
+ expect(r.agentsMd).toBe('exists');
125
+ expect(r.cursorRules).toBe('exists');
126
+ });
127
+ it('skips .cursorrules when cursor: false', () => {
128
+ const r = (0, agents_md_1.writeCellRules)(tmpDir, { cursor: false });
129
+ expect(r.agentsMd).toBe('written');
130
+ expect(r.cursorRules).toBe('skipped');
131
+ expect(fs.existsSync(path.join(tmpDir, agents_md_1.CURSORRULES_FILENAME))).toBe(false);
132
+ });
133
+ });
134
+ describe('filename constants', () => {
135
+ it('exports the correct filenames', () => {
136
+ expect(agents_md_1.AGENTS_MD_FILENAME).toBe('AGENTS.md');
137
+ expect(agents_md_1.CURSORRULES_FILENAME).toBe('.cursorrules');
138
+ });
139
+ });
140
+ });
141
+ //# sourceMappingURL=agents-md.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-md.test.js","sourceRoot":"","sources":["../../src/__tests__/agents-md.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=atcell-live-fallback.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atcell-live-fallback.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/atcell-live-fallback.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const prompt_builder_1 = require("../core/prompt-builder");
4
+ const mockDb = {
5
+ prepare: jest.fn(),
6
+ };
7
+ jest.mock('../core/database', () => ({
8
+ getDb: () => mockDb,
9
+ }));
10
+ function fakeStmt(rows) {
11
+ return {
12
+ all: (..._args) => rows,
13
+ get: (..._args) => rows[0] || undefined,
14
+ };
15
+ }
16
+ describe('@cell live_event fallback (regression for v4.1.8 UX bug)', () => {
17
+ function setupMocks(opts = {}) {
18
+ const profileTs = opts.profileScannedAt || new Date().toISOString();
19
+ mockDb.prepare.mockReset();
20
+ mockDb.prepare.mockImplementation((sql) => {
21
+ const s = sql.trim().toUpperCase();
22
+ if (s.startsWith('SELECT * FROM DEVELOPER_PROFILES')) {
23
+ return fakeStmt([{ id: 1, project: 'fivo-cell', files_scanned: 100, total_lines: 5000, scanned_at: profileTs }]);
24
+ }
25
+ if (s.startsWith('SELECT PATTERN_TYPE, PATTERN_VALUE, CATEGORY, COUNT, TRUST_SCORE FROM CODE_PATTERNS')) {
26
+ if (s.includes("CATEGORY = 'BLIND_SPOTS'"))
27
+ return fakeStmt([]);
28
+ return fakeStmt([{ pattern_type: 'naming', pattern_value: 'camelCase', category: 'naming', count: 10, trust_score: 90 }]);
29
+ }
30
+ if (s.startsWith('SELECT * FROM SCANS')) {
31
+ return fakeStmt([{ id: 1, project: 'fivo-cell', started_at: new Date().toISOString(), completed_at: new Date().toISOString(), files_scanned: 100 }]);
32
+ }
33
+ if (s.startsWith('SELECT * FROM ERROR_LOG'))
34
+ return fakeStmt([]);
35
+ if (s.startsWith('SELECT PATTERN_VALUE FROM CODE_PATTERNS'))
36
+ return fakeStmt([]);
37
+ if (s.startsWith('SELECT * FROM SESSIONS')) {
38
+ return fakeStmt(opts.sessionRows || []);
39
+ }
40
+ if (s.startsWith('SELECT * FROM LIVE_EVENTS')) {
41
+ return opts.liveEventRows ? fakeStmt(opts.liveEventRows) : fakeStmt([]);
42
+ }
43
+ if (s.includes('SESSION_APPROACHES') && s.includes('GROUP BY'))
44
+ return fakeStmt([]);
45
+ if (s.startsWith('SELECT FILE_PATH') && s.includes('SESSION_FILES'))
46
+ return fakeStmt([]);
47
+ if (s.startsWith('SELECT * FROM SESSION_QUESTIONS'))
48
+ return fakeStmt([]);
49
+ return fakeStmt([]);
50
+ });
51
+ }
52
+ it('sets lastLiveFile when no session exists but live_events has rows', () => {
53
+ const eventTs = new Date(Date.now() - 60_000).toISOString();
54
+ setupMocks({
55
+ sessionRows: [],
56
+ liveEventRows: [{ id: 1217, project: 'fivo-cell', event_type: 'file_save', file_path: 'src/components/layout/AppLayout.tsx', created_at: eventTs }],
57
+ });
58
+ const ctx = (0, prompt_builder_1.buildContext)('fivo-cell', 'claude-code');
59
+ expect(ctx.lastSession).toBeUndefined();
60
+ expect(ctx.lastLiveFile).toBeDefined();
61
+ expect(ctx.lastLiveFile?.filePath).toBe('src/components/layout/AppLayout.tsx');
62
+ expect(ctx.lastLiveFile?.eventType).toBe('file_save');
63
+ });
64
+ it('@cell block shows "Live: saved <path>" when only live_event is present (regression for empty Last Session)', () => {
65
+ const eventTs = new Date(Date.now() - 30_000).toISOString();
66
+ setupMocks({
67
+ sessionRows: [],
68
+ liveEventRows: [{ id: 50, project: 'fivo-cell', event_type: 'file_save', file_path: 'src/foo.ts', created_at: eventTs }],
69
+ });
70
+ const ctx = (0, prompt_builder_1.buildContext)('fivo-cell', 'claude-code');
71
+ const out = (0, prompt_builder_1.formatContextForTool)(ctx, 'claude-code');
72
+ expect(out).toContain('Live: saved src/foo.ts');
73
+ expect(out).not.toContain('(no session yet — first run)');
74
+ expect(out).toContain('cell session start');
75
+ });
76
+ it('@cell block shows "Live: created <path>" for file_create events', () => {
77
+ const eventTs = new Date().toISOString();
78
+ setupMocks({
79
+ sessionRows: [],
80
+ liveEventRows: [{ id: 51, project: 'fivo-cell', event_type: 'file_create', file_path: 'src/new.ts', created_at: eventTs }],
81
+ });
82
+ const ctx = (0, prompt_builder_1.buildContext)('fivo-cell', 'claude-code');
83
+ const out = (0, prompt_builder_1.formatContextForTool)(ctx, 'claude-code');
84
+ expect(out).toContain('Live: created src/new.ts');
85
+ });
86
+ it('@cell block shows "Live: deleted <path>" for file_delete events', () => {
87
+ const eventTs = new Date().toISOString();
88
+ setupMocks({
89
+ sessionRows: [],
90
+ liveEventRows: [{ id: 52, project: 'fivo-cell', event_type: 'file_delete', file_path: 'src/old.ts', created_at: eventTs }],
91
+ });
92
+ const ctx = (0, prompt_builder_1.buildContext)('fivo-cell', 'claude-code');
93
+ const out = (0, prompt_builder_1.formatContextForTool)(ctx, 'claude-code');
94
+ expect(out).toContain('Live: deleted src/old.ts');
95
+ });
96
+ it('prefers lastSession over lastLiveFile when both exist (session is richer context)', () => {
97
+ const eventTs = new Date(Date.now() - 30_000).toISOString();
98
+ setupMocks({
99
+ sessionRows: [{
100
+ id: 5, tool_name: 'cursor', project: 'fivo-cell',
101
+ start_time: new Date(Date.now() - 600_000).toISOString(),
102
+ end_time: new Date().toISOString(),
103
+ files_touched: '["src/session-tracker.ts"]',
104
+ key_decisions: '["Phase 2"]',
105
+ context_snapshot: 'Working on session data',
106
+ }],
107
+ liveEventRows: [{ id: 100, project: 'fivo-cell', event_type: 'file_save', file_path: 'src/recent.ts', created_at: eventTs }],
108
+ });
109
+ const ctx = (0, prompt_builder_1.buildContext)('fivo-cell', 'claude-code');
110
+ expect(ctx.lastSession).toBeDefined();
111
+ expect(ctx.lastLiveFile).toBeDefined();
112
+ const out = (0, prompt_builder_1.formatContextForTool)(ctx, 'claude-code');
113
+ expect(out).toContain('Tool: cursor');
114
+ expect(out).toContain('Working on: Working on session data');
115
+ // Should NOT show the live fallback when a session exists
116
+ expect(out).not.toContain('Live: saved');
117
+ });
118
+ it('shows cold-start message when neither session nor live events exist', () => {
119
+ setupMocks({ sessionRows: [], liveEventRows: [] });
120
+ const ctx = (0, prompt_builder_1.buildContext)('unknown-project', 'claude-code');
121
+ expect(ctx.lastSession).toBeUndefined();
122
+ expect(ctx.lastLiveFile).toBeUndefined();
123
+ const out = (0, prompt_builder_1.formatContextForTool)(ctx, 'claude-code');
124
+ expect(out).toContain('(no session yet — first run)');
125
+ });
126
+ it('handles live_events query failure gracefully (returns undefined, does not crash)', () => {
127
+ setupMocks({ sessionRows: [] });
128
+ mockDb.prepare.mockImplementation((sql) => {
129
+ if (sql.trim().toUpperCase().startsWith('SELECT * FROM LIVE_EVENTS')) {
130
+ throw new Error('table missing');
131
+ }
132
+ return fakeStmt([]);
133
+ });
134
+ const ctx = (0, prompt_builder_1.buildContext)('fivo-cell', 'claude-code');
135
+ expect(ctx.lastLiveFile).toBeUndefined();
136
+ });
137
+ });
138
+ //# sourceMappingURL=atcell-live-fallback.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atcell-live-fallback.test.js","sourceRoot":"","sources":["../../src/__tests__/atcell-live-fallback.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=watch-cli.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-cli.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/watch-cli.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const watch_cli_1 = require("../core/watch-cli");
4
+ describe('watch-cli parser (cell watch events --limit/--type)', () => {
5
+ describe('parseWatchFlags', () => {
6
+ it('returns all positional args when no flags present', () => {
7
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '/path/to/dir']);
8
+ expect(r.positional).toEqual(['fivo-cell', '/path/to/dir']);
9
+ });
10
+ it('strips --limit N flag from positional list', () => {
11
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '--limit', '10']);
12
+ expect(r.positional).toEqual(['fivo-cell']);
13
+ });
14
+ it('strips --limit=N form', () => {
15
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '--limit=10']);
16
+ expect(r.positional).toEqual(['fivo-cell']);
17
+ });
18
+ it('strips --type file_save flag', () => {
19
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '--type', 'file_save']);
20
+ expect(r.positional).toEqual(['fivo-cell']);
21
+ });
22
+ it('strips --type=file_save form', () => {
23
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '--type=file_save']);
24
+ expect(r.positional).toEqual(['fivo-cell']);
25
+ });
26
+ it('handles flags before and after positional args (regression for v4.1.8 bug where --limit became project name)', () => {
27
+ const r = (0, watch_cli_1.parseWatchFlags)(['--limit', '3', 'fivo-cell', '--type', 'file_save']);
28
+ expect(r.positional).toEqual(['fivo-cell']);
29
+ });
30
+ it('ignores unknown --flags without breaking (treats them as no-arg switches)', () => {
31
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '--unknown', 'value', '/dir']);
32
+ expect(r.positional).toEqual(['fivo-cell', 'value', '/dir']);
33
+ });
34
+ it('returns empty list when only flags provided', () => {
35
+ const r = (0, watch_cli_1.parseWatchFlags)(['--limit', '5', '--type', 'file_save']);
36
+ expect(r.positional).toEqual([]);
37
+ });
38
+ it('handles --limit at end of args (no value)', () => {
39
+ const r = (0, watch_cli_1.parseWatchFlags)(['fivo-cell', '--limit']);
40
+ expect(r.positional).toEqual(['fivo-cell']);
41
+ });
42
+ });
43
+ describe('parseWatchLimit', () => {
44
+ it('returns default when no flag present', () => {
45
+ expect((0, watch_cli_1.parseWatchLimit)(['fivo-cell'])).toBe(watch_cli_1.DEFAULT_EVENT_LIMIT);
46
+ expect((0, watch_cli_1.parseWatchLimit)([])).toBe(watch_cli_1.DEFAULT_EVENT_LIMIT);
47
+ });
48
+ it('parses --limit N form', () => {
49
+ expect((0, watch_cli_1.parseWatchLimit)(['fivo-cell', '--limit', '50'])).toBe(50);
50
+ });
51
+ it('parses --limit=N form', () => {
52
+ expect((0, watch_cli_1.parseWatchLimit)(['fivo-cell', '--limit=42'])).toBe(42);
53
+ });
54
+ it('clamps absurdly large values to MAX_EVENT_LIMIT', () => {
55
+ expect((0, watch_cli_1.parseWatchLimit)(['--limit', '99999'])).toBe(watch_cli_1.MAX_EVENT_LIMIT);
56
+ });
57
+ it('falls back to default for non-numeric input', () => {
58
+ expect((0, watch_cli_1.parseWatchLimit)(['--limit', 'abc'])).toBe(watch_cli_1.DEFAULT_EVENT_LIMIT);
59
+ });
60
+ it('falls back to default for zero or negative', () => {
61
+ expect((0, watch_cli_1.parseWatchLimit)(['--limit', '0'])).toBe(watch_cli_1.DEFAULT_EVENT_LIMIT);
62
+ expect((0, watch_cli_1.parseWatchLimit)(['--limit', '-5'])).toBe(watch_cli_1.DEFAULT_EVENT_LIMIT);
63
+ });
64
+ it('uses custom fallback when provided', () => {
65
+ expect((0, watch_cli_1.parseWatchLimit)([], 100)).toBe(100);
66
+ });
67
+ });
68
+ describe('parseWatchEventType', () => {
69
+ it('returns undefined when no flag present', () => {
70
+ expect((0, watch_cli_1.parseWatchEventType)(['fivo-cell'])).toBeUndefined();
71
+ expect((0, watch_cli_1.parseWatchEventType)([])).toBeUndefined();
72
+ });
73
+ it('parses --type T form', () => {
74
+ expect((0, watch_cli_1.parseWatchEventType)(['--type', 'file_save'])).toBe('file_save');
75
+ });
76
+ it('parses --type=T form', () => {
77
+ expect((0, watch_cli_1.parseWatchEventType)(['--type=file_delete'])).toBe('file_delete');
78
+ });
79
+ it('works with positional args before/after', () => {
80
+ expect((0, watch_cli_1.parseWatchEventType)(['fivo-cell', '--type', 'git_commit'])).toBe('git_commit');
81
+ expect((0, watch_cli_1.parseWatchEventType)(['--type', 'file_rename', 'fivo-cell'])).toBe('file_rename');
82
+ });
83
+ });
84
+ describe('isValidEventType', () => {
85
+ it('accepts all known event types', () => {
86
+ for (const t of ['file_save', 'file_create', 'file_delete', 'file_rename', 'git_commit', 'package_change']) {
87
+ expect((0, watch_cli_1.isValidEventType)(t)).toBe(true);
88
+ }
89
+ });
90
+ it('rejects unknown types', () => {
91
+ expect((0, watch_cli_1.isValidEventType)('foo')).toBe(false);
92
+ expect((0, watch_cli_1.isValidEventType)('FILE_SAVE')).toBe(false);
93
+ expect((0, watch_cli_1.isValidEventType)(undefined)).toBe(false);
94
+ expect((0, watch_cli_1.isValidEventType)('')).toBe(false);
95
+ });
96
+ });
97
+ });
98
+ //# sourceMappingURL=watch-cli.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch-cli.test.js","sourceRoot":"","sources":["../../src/__tests__/watch-cli.test.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -300,19 +300,46 @@ function doScan() {
300
300
  const banner = figlet_1.default.textSync('CELL', { font: 'ANSI Shadow', horizontalLayout: 'fitted' });
301
301
  console.log((0, gradient_string_1.default)(['#FF6B35', '#FFAB91'])(banner));
302
302
  console.log(C.dim(' Scanning codebase + building all layers...\n'));
303
+ // ─── Flag parsing ─────────────────────────────────────────────────────
304
+ // --no-rules → skip writing AGENTS.md and .cursorrules to project root
305
+ // --force-rules → overwrite existing AGENTS.md/.cursorrules (otherwise keep user edits)
306
+ const noRules = args.includes('--no-rules');
307
+ const forceRules = args.includes('--force-rules');
308
+ const scanPathArg = args.find((a, i) => i >= 1 && !a.startsWith('--')) || project;
309
+ const scanCwd = path.resolve(scanPathArg);
310
+ const scanProject = path.basename(scanCwd);
303
311
  try {
304
312
  const { scanCodebase } = require('./code-scanner');
305
- const result = scanCodebase(process.cwd(), project);
313
+ const result = scanCodebase(scanCwd, scanProject);
306
314
  console.log(C.success(` [1/2] Scanned ${result.filesScanned} files, ${result.totalLines.toLocaleString()} lines`));
307
315
  (0, layers_1.populateAllLayers)({
308
316
  profile: result.profile,
309
317
  patterns: result.patterns,
310
- project,
318
+ project: scanProject,
311
319
  });
312
320
  console.log(C.success(' [2/2] Populated all layers:'));
313
321
  console.log(C.dim(' .cell/personal/ — profile, style, errors, decisions'));
314
322
  console.log(C.dim(' .cell/team/ — shared patterns, blind spots'));
315
323
  console.log(C.dim(' .cell/community/ — community patterns, trends'));
324
+ // ─── AI rules files (AGENTS.md, .cursorrules) ─────────────────────────
325
+ if (!noRules) {
326
+ const { writeCellRules } = require('./core/agents-md');
327
+ const rulesResult = writeCellRules(scanCwd, { overwrite: forceRules });
328
+ const lines = [];
329
+ if (rulesResult.agentsMd === 'written')
330
+ lines.push('AGENTS.md');
331
+ if (rulesResult.cursorRules === 'written')
332
+ lines.push('.cursorrules');
333
+ if (lines.length > 0) {
334
+ console.log(C.success(` [3/3] Wrote AI rules: ${lines.join(', ')} (idempotent — kept existing files)`));
335
+ }
336
+ else {
337
+ console.log(C.dim(' [3/3] AI rules: AGENTS.md + .cursorrules already present (kept as-is)'));
338
+ }
339
+ }
340
+ else {
341
+ console.log(C.dim(' [3/3] AI rules: skipped (--no-rules)'));
342
+ }
316
343
  console.log();
317
344
  console.log(C.dim(' Run: cell status'));
318
345
  console.log();
@@ -988,8 +1015,19 @@ function doWatch() {
988
1015
  console.log(C.dim(' ─────────────────'));
989
1016
  console.log();
990
1017
  const sub = args[1] || 'daemon';
991
- const project = args[2] || path.basename(process.cwd());
992
- const dir = args[3] || process.cwd();
1018
+ // Parse flags first so positional args don't get eaten by --limit / --type.
1019
+ // Examples supported:
1020
+ // cell watch events
1021
+ // cell watch events fivo-cell
1022
+ // cell watch events fivo-cell --limit 10
1023
+ // cell watch events fivo-cell --type file_save
1024
+ // cell watch events --limit 5 --type file_create
1025
+ const watchArgs = args.slice(2);
1026
+ const { positional } = require('./core/watch-cli').parseWatchFlags(watchArgs);
1027
+ const watchLimit = require('./core/watch-cli').parseWatchLimit(watchArgs);
1028
+ const watchEventType = require('./core/watch-cli').parseWatchEventType(watchArgs);
1029
+ const project = positional[0] || path.basename(process.cwd());
1030
+ const dir = positional[1] || process.cwd();
993
1031
  // If invoked with no subcommand: run as a long-lived watcher daemon (for .bat auto-restart loop)
994
1032
  if (sub === 'daemon' || sub === '') {
995
1033
  runWatchDaemon(project, dir);
@@ -1037,14 +1075,22 @@ function doWatch() {
1037
1075
  return;
1038
1076
  }
1039
1077
  if (sub === 'events') {
1040
- const events = liveWatcher.getLiveEvents(project, 20);
1078
+ const { isValidEventType } = require('./core/watch-cli');
1079
+ const typeFilter = isValidEventType(watchEventType) ? watchEventType : undefined;
1080
+ const events = liveWatcher.getLiveEvents(project, watchLimit, typeFilter);
1041
1081
  if (events.length === 0) {
1042
- console.log(C.dim(` No live events for ${project} yet. Start watcher with: cell watch start ${project}`));
1082
+ const hint = typeFilter
1083
+ ? `No ${typeFilter} events for ${project} in the last ${watchLimit}.`
1084
+ : `No live events for ${project} yet. Start watcher with: cell watch start ${project}`;
1085
+ console.log(C.dim(` ${hint}`));
1043
1086
  }
1044
1087
  else {
1045
- console.log(C.bold(` Recent events for ${project} (${events.length}):`));
1088
+ const header = typeFilter
1089
+ ? `Recent ${typeFilter} events for ${project} (${events.length}, limit ${watchLimit}):`
1090
+ : `Recent events for ${project} (${events.length}, limit ${watchLimit}):`;
1091
+ console.log(C.bold(` ${header}`));
1046
1092
  for (const e of events) {
1047
- const icon = e.eventType === 'file_save' ? '~' : e.eventType === 'file_create' ? '+' : e.eventType === 'file_delete' ? '-' : '*';
1093
+ const icon = e.eventType === 'file_save' ? '~' : e.eventType === 'file_create' ? '+' : e.eventType === 'file_delete' ? '-' : e.eventType === 'file_rename' ? '>' : e.eventType === 'git_commit' ? '@' : '*';
1048
1094
  console.log(` ${C.dim(icon)} ${C.dim(e.createdAt)} ${e.eventType}: ${C.num(e.filePath)}`);
1049
1095
  }
1050
1096
  }