@productbrain/cli 0.1.0-beta.71 → 0.1.0-beta.72

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.
Files changed (80) hide show
  1. package/dist/__tests__/audit.test.js +44 -44
  2. package/dist/__tests__/capture.test.js +37 -37
  3. package/dist/__tests__/constellation.test.js +14 -14
  4. package/dist/__tests__/context-strategy.test.js +8 -8
  5. package/dist/__tests__/fields.test.js +20 -20
  6. package/dist/__tests__/ingest.test.js +28 -28
  7. package/dist/__tests__/orient.test.js +8 -8
  8. package/dist/__tests__/promote.test.js +15 -15
  9. package/dist/__tests__/proposals.test.js +18 -18
  10. package/dist/__tests__/relate.test.js +14 -14
  11. package/dist/__tests__/session-touch.test.js +11 -11
  12. package/dist/__tests__/session.test.js +2 -2
  13. package/dist/__tests__/setup.test.js +7 -7
  14. package/dist/__tests__/update.test.js +21 -21
  15. package/dist/__tests__/workspace.test.js +20 -20
  16. package/dist/commands/accept.js +4 -4
  17. package/dist/commands/admin/cockpit.d.ts +4 -2
  18. package/dist/commands/admin/cockpit.d.ts.map +1 -1
  19. package/dist/commands/admin/cockpit.js +213 -6
  20. package/dist/commands/admin/cockpit.js.map +1 -1
  21. package/dist/commands/admin/index.d.ts.map +1 -1
  22. package/dist/commands/admin/index.js +2 -0
  23. package/dist/commands/admin/index.js.map +1 -1
  24. package/dist/commands/admin/inspect.d.ts +9 -0
  25. package/dist/commands/admin/inspect.d.ts.map +1 -1
  26. package/dist/commands/admin/inspect.js +19 -0
  27. package/dist/commands/admin/inspect.js.map +1 -1
  28. package/dist/commands/admin/inspect.test.js +20 -1
  29. package/dist/commands/admin/inspect.test.js.map +1 -1
  30. package/dist/commands/admin/manage.d.ts +8 -0
  31. package/dist/commands/admin/manage.d.ts.map +1 -0
  32. package/dist/commands/admin/manage.js +76 -0
  33. package/dist/commands/admin/manage.js.map +1 -0
  34. package/dist/commands/audit.js +4 -4
  35. package/dist/commands/brief.js +4 -4
  36. package/dist/commands/capture.js +6 -6
  37. package/dist/commands/chain-walk.js +2 -2
  38. package/dist/commands/changes.js +2 -2
  39. package/dist/commands/codex-prep.js +2 -2
  40. package/dist/commands/collections.js +5 -5
  41. package/dist/commands/constellation.js +2 -2
  42. package/dist/commands/context.js +2 -2
  43. package/dist/commands/cross-cut.js +2 -2
  44. package/dist/commands/doctor.js +3 -3
  45. package/dist/commands/doctor.test.js +1 -1
  46. package/dist/commands/fields.js +2 -2
  47. package/dist/commands/get.js +3 -3
  48. package/dist/commands/handshake.js +5 -5
  49. package/dist/commands/ingest.js +6 -6
  50. package/dist/commands/init.d.ts +1 -1
  51. package/dist/commands/init.js +1 -1
  52. package/dist/commands/orient.js +2 -2
  53. package/dist/commands/promote.js +4 -4
  54. package/dist/commands/proposals.js +2 -2
  55. package/dist/commands/reject.js +2 -2
  56. package/dist/commands/relate.js +3 -3
  57. package/dist/commands/search.js +2 -2
  58. package/dist/commands/session.js +7 -7
  59. package/dist/commands/setup.js +5 -5
  60. package/dist/commands/update.js +3 -3
  61. package/dist/commands/usage.d.ts +1 -1
  62. package/dist/commands/usage.js +4 -4
  63. package/dist/commands/verify.js +2 -2
  64. package/dist/commands/workspace.js +4 -4
  65. package/dist/generators/chain-rules.d.ts +3 -3
  66. package/dist/generators/chain-rules.js +3 -3
  67. package/dist/generators/chain-rules.test.js +2 -2
  68. package/dist/generators/portable-knowledge.js +1 -1
  69. package/dist/index.js +1 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/lib/activation.js +2 -2
  72. package/dist/lib/activation.test.js +3 -3
  73. package/dist/lib/client.d.ts +4 -4
  74. package/dist/lib/client.js +8 -8
  75. package/dist/lib/client.js.map +1 -1
  76. package/dist/lib/onboarding-path-b.js +8 -8
  77. package/dist/lib/onboarding-shared.js +2 -2
  78. package/dist/lib/onboarding.js +4 -4
  79. package/dist/lib/workspace-probe.js +2 -2
  80. package/package.json +1 -1
@@ -1,12 +1,12 @@
1
1
  /**
2
- * pb promote — verify convexCallWithSession sequence and args.
2
+ * pb promote — verify kernelCallWithSession sequence and args.
3
3
  * Covers: happy path (direct commit), governance proposal, no session, empty entryId.
4
4
  */
5
5
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
6
  import { runPromote } from '../commands/promote.js';
7
- const convexCallWithSessionMock = vi.fn();
7
+ const kernelCallWithSessionMock = vi.fn();
8
8
  vi.mock('../lib/client.js', () => ({
9
- convexCallWithSession: (...args) => convexCallWithSessionMock(...args),
9
+ kernelCallWithSession: (...args) => kernelCallWithSessionMock(...args),
10
10
  }));
11
11
  vi.mock('../lib/config.js', () => ({
12
12
  getConfigOrGuide: vi.fn(() => Promise.resolve({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
@@ -29,7 +29,7 @@ describe('runPromote', () => {
29
29
  mockSession = { sessionId: 'sess-test' };
30
30
  });
31
31
  it('calls chain.commitEntry with correct args (happy path)', async () => {
32
- convexCallWithSessionMock
32
+ kernelCallWithSessionMock
33
33
  .mockResolvedValueOnce({ name: 'Test entry', collectionSlug: 'tensions', data: { description: 'Valid description' } })
34
34
  .mockResolvedValueOnce([])
35
35
  .mockResolvedValueOnce({
@@ -41,14 +41,14 @@ describe('runPromote', () => {
41
41
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
42
42
  await runPromote({ entryId: 'TEN-951' });
43
43
  writeSpy.mockRestore();
44
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.commitEntry', {
44
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.commitEntry', {
45
45
  entryId: 'TEN-951',
46
46
  author: 'agent:sess-test',
47
47
  sessionId: 'sess-test',
48
48
  });
49
49
  });
50
50
  it('passes commitMessage when --message is provided', async () => {
51
- convexCallWithSessionMock
51
+ kernelCallWithSessionMock
52
52
  .mockResolvedValueOnce({ name: 'Test entry', collectionSlug: 'tensions', data: { description: 'Valid description' } })
53
53
  .mockResolvedValueOnce([])
54
54
  .mockResolvedValueOnce({
@@ -60,7 +60,7 @@ describe('runPromote', () => {
60
60
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
61
61
  await runPromote({ entryId: 'TEN-951', message: 'Validated and ready' });
62
62
  writeSpy.mockRestore();
63
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.commitEntry', {
63
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.commitEntry', {
64
64
  entryId: 'TEN-951',
65
65
  author: 'agent:sess-test',
66
66
  sessionId: 'sess-test',
@@ -68,7 +68,7 @@ describe('runPromote', () => {
68
68
  });
69
69
  });
70
70
  it('displays version result for direct commit', async () => {
71
- convexCallWithSessionMock
71
+ kernelCallWithSessionMock
72
72
  .mockResolvedValueOnce({ name: 'Wave 2 smoke test', collectionSlug: 'tensions', data: { description: 'Valid description' } })
73
73
  .mockResolvedValueOnce([])
74
74
  .mockResolvedValueOnce({
@@ -88,7 +88,7 @@ describe('runPromote', () => {
88
88
  expect(output).toContain('v1');
89
89
  });
90
90
  it('displays proposal result for governance mode', async () => {
91
- convexCallWithSessionMock
91
+ kernelCallWithSessionMock
92
92
  .mockResolvedValueOnce({ name: 'Some governed decision', collectionSlug: 'decisions', data: { rationale: 'Valid description' } })
93
93
  .mockResolvedValueOnce([])
94
94
  .mockResolvedValueOnce({
@@ -107,7 +107,7 @@ describe('runPromote', () => {
107
107
  expect(output).toContain('governance mode');
108
108
  });
109
109
  it('displays quality warnings when present', async () => {
110
- convexCallWithSessionMock
110
+ kernelCallWithSessionMock
111
111
  .mockResolvedValueOnce({ name: 'Test Bet', collectionSlug: 'bets', data: { description: 'Valid description' } })
112
112
  .mockResolvedValueOnce([])
113
113
  .mockResolvedValueOnce({
@@ -132,18 +132,18 @@ describe('runPromote', () => {
132
132
  it('throws CLIError with no active session', async () => {
133
133
  mockSession = null;
134
134
  await expect(runPromote({ entryId: 'TEN-951' })).rejects.toThrow('No active session');
135
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
135
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
136
136
  });
137
137
  it('throws CLIError with empty entryId', async () => {
138
138
  await expect(runPromote({ entryId: ' ' })).rejects.toThrow('Entry ID is required');
139
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
139
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
140
140
  });
141
141
  it('handles server errors thrown during commit', async () => {
142
- convexCallWithSessionMock.mockRejectedValue(new Error('Entry not found.'));
142
+ kernelCallWithSessionMock.mockRejectedValue(new Error('Entry not found.'));
143
143
  await expect(runPromote({ entryId: 'TEN-999' })).rejects.toThrow('Entry not found.');
144
144
  });
145
145
  it('blocks promote when semantic contradiction preflight finds a contradiction', async () => {
146
- convexCallWithSessionMock
146
+ kernelCallWithSessionMock
147
147
  .mockResolvedValueOnce({ name: 'Conflicting entry', collectionSlug: 'decisions', data: { rationale: 'Valid description' } })
148
148
  .mockResolvedValueOnce([
149
149
  {
@@ -155,7 +155,7 @@ describe('runPromote', () => {
155
155
  },
156
156
  ]);
157
157
  await expect(runPromote({ entryId: 'DEC-100' })).rejects.toThrow('Commit blocked by contradiction with DEC-42: Directly contradicts the approved baseline.');
158
- expect(convexCallWithSessionMock).not.toHaveBeenCalledWith('chain.commitEntry', expect.anything());
158
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalledWith('chain.commitEntry', expect.anything());
159
159
  });
160
160
  });
161
161
  //# sourceMappingURL=promote.test.js.map
@@ -13,9 +13,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
13
13
  import { runProposals } from '../commands/proposals.js';
14
14
  import { runAccept } from '../commands/accept.js';
15
15
  import { runReject } from '../commands/reject.js';
16
- const convexCallMock = vi.fn();
16
+ const kernelCallMock = vi.fn();
17
17
  vi.mock('../lib/client.js', () => ({
18
- convexCall: (...args) => convexCallMock(...args),
18
+ kernelCall: (...args) => kernelCallMock(...args),
19
19
  }));
20
20
  vi.mock('../lib/config.js', () => ({
21
21
  getConfigOrGuide: vi.fn(() => Promise.resolve({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
@@ -48,16 +48,16 @@ describe('runProposals', () => {
48
48
  vi.clearAllMocks();
49
49
  });
50
50
  it('formats empty proposal list', async () => {
51
- convexCallMock.mockResolvedValue([]);
51
+ kernelCallMock.mockResolvedValue([]);
52
52
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
53
53
  await runProposals();
54
54
  const output = writeSpy.mock.calls.map((c) => String(c[0])).join('');
55
55
  writeSpy.mockRestore();
56
56
  expect(output).toContain('No open consent proposals');
57
- expect(convexCallMock).toHaveBeenCalledWith('governance.listProposals', {});
57
+ expect(kernelCallMock).toHaveBeenCalledWith('governance.listProposals', {});
58
58
  });
59
59
  it('formats non-empty proposal list with expiry', async () => {
60
- convexCallMock.mockResolvedValue([sampleProposal]);
60
+ kernelCallMock.mockResolvedValue([sampleProposal]);
61
61
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
62
62
  await runProposals();
63
63
  const output = writeSpy.mock.calls.map((c) => String(c[0])).join('');
@@ -74,7 +74,7 @@ describe('runAccept', () => {
74
74
  vi.clearAllMocks();
75
75
  });
76
76
  it('calls governance.respondToProposal with approve verdict', async () => {
77
- convexCallMock.mockResolvedValue({
77
+ kernelCallMock.mockResolvedValue({
78
78
  status: 'approved',
79
79
  proposalId: 'prop-abc123',
80
80
  message: 'Proposal approved. Governs relation created.',
@@ -83,7 +83,7 @@ describe('runAccept', () => {
83
83
  await runAccept({ proposalId: 'prop-abc123' });
84
84
  const output = writeSpy.mock.calls.map((c) => String(c[0])).join('');
85
85
  writeSpy.mockRestore();
86
- expect(convexCallMock).toHaveBeenCalledWith('governance.respondToProposal', {
86
+ expect(kernelCallMock).toHaveBeenCalledWith('governance.respondToProposal', {
87
87
  proposalId: 'prop-abc123',
88
88
  verdict: 'approve',
89
89
  });
@@ -98,9 +98,9 @@ describe('runAccept', () => {
98
98
  };
99
99
  const freshProposal = { ...sampleProposal, _id: 'prop-fresh' };
100
100
  // First call: listProposals
101
- convexCallMock.mockResolvedValueOnce([expiredProposal, freshProposal]);
101
+ kernelCallMock.mockResolvedValueOnce([expiredProposal, freshProposal]);
102
102
  // Second call: respondToProposal for fresh proposal
103
- convexCallMock.mockResolvedValueOnce({
103
+ kernelCallMock.mockResolvedValueOnce({
104
104
  status: 'approved',
105
105
  proposalId: 'prop-fresh',
106
106
  message: 'Proposal approved. Governs relation created.',
@@ -110,9 +110,9 @@ describe('runAccept', () => {
110
110
  const output = writeSpy.mock.calls.map((c) => String(c[0])).join('');
111
111
  writeSpy.mockRestore();
112
112
  // Should have called listProposals, then respondToProposal for fresh only
113
- expect(convexCallMock).toHaveBeenCalledTimes(2);
114
- expect(convexCallMock).toHaveBeenNthCalledWith(1, 'governance.listProposals', {});
115
- expect(convexCallMock).toHaveBeenNthCalledWith(2, 'governance.respondToProposal', {
113
+ expect(kernelCallMock).toHaveBeenCalledTimes(2);
114
+ expect(kernelCallMock).toHaveBeenNthCalledWith(1, 'governance.listProposals', {});
115
+ expect(kernelCallMock).toHaveBeenNthCalledWith(2, 'governance.respondToProposal', {
116
116
  proposalId: 'prop-fresh',
117
117
  verdict: 'approve',
118
118
  });
@@ -122,7 +122,7 @@ describe('runAccept', () => {
122
122
  expect(output).toContain('Expired');
123
123
  });
124
124
  it('--auto with no proposals reports nothing to process', async () => {
125
- convexCallMock.mockResolvedValueOnce([]);
125
+ kernelCallMock.mockResolvedValueOnce([]);
126
126
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
127
127
  await runAccept({ auto: true });
128
128
  const output = writeSpy.mock.calls.map((c) => String(c[0])).join('');
@@ -131,7 +131,7 @@ describe('runAccept', () => {
131
131
  });
132
132
  it('throws CLIError when no proposal-id and no --auto', async () => {
133
133
  await expect(runAccept({})).rejects.toThrow('Proposal ID is required');
134
- expect(convexCallMock).not.toHaveBeenCalled();
134
+ expect(kernelCallMock).not.toHaveBeenCalled();
135
135
  });
136
136
  });
137
137
  describe('runReject', () => {
@@ -139,7 +139,7 @@ describe('runReject', () => {
139
139
  vi.clearAllMocks();
140
140
  });
141
141
  it('calls governance.respondToProposal with reject verdict and reason', async () => {
142
- convexCallMock.mockResolvedValue({
142
+ kernelCallMock.mockResolvedValue({
143
143
  status: 'objected',
144
144
  proposalId: 'prop-abc123',
145
145
  message: 'Proposal rejected: Creates circular governance',
@@ -148,7 +148,7 @@ describe('runReject', () => {
148
148
  await runReject({ proposalId: 'prop-abc123', reason: 'Creates circular governance' });
149
149
  const output = writeSpy.mock.calls.map((c) => String(c[0])).join('');
150
150
  writeSpy.mockRestore();
151
- expect(convexCallMock).toHaveBeenCalledWith('governance.respondToProposal', {
151
+ expect(kernelCallMock).toHaveBeenCalledWith('governance.respondToProposal', {
152
152
  proposalId: 'prop-abc123',
153
153
  verdict: 'reject',
154
154
  reason: 'Creates circular governance',
@@ -157,11 +157,11 @@ describe('runReject', () => {
157
157
  });
158
158
  it('throws CLIError when reason is empty', async () => {
159
159
  await expect(runReject({ proposalId: 'prop-abc123', reason: '' })).rejects.toThrow('reason is required');
160
- expect(convexCallMock).not.toHaveBeenCalled();
160
+ expect(kernelCallMock).not.toHaveBeenCalled();
161
161
  });
162
162
  it('throws CLIError when proposal-id is empty', async () => {
163
163
  await expect(runReject({ proposalId: '', reason: 'Some reason' })).rejects.toThrow('Proposal ID is required');
164
- expect(convexCallMock).not.toHaveBeenCalled();
164
+ expect(kernelCallMock).not.toHaveBeenCalled();
165
165
  });
166
166
  });
167
167
  //# sourceMappingURL=proposals.test.js.map
@@ -1,12 +1,12 @@
1
1
  /**
2
- * pb relate / pb unrelate — verify convexCallWithSession sequence and args.
2
+ * pb relate / pb unrelate — verify kernelCallWithSession sequence and args.
3
3
  * TEN-341 test contract: happy paths, no session.
4
4
  */
5
5
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
6
  import { runRelate, runUnrelate } from '../commands/relate.js';
7
- const convexCallWithSessionMock = vi.fn();
7
+ const kernelCallWithSessionMock = vi.fn();
8
8
  vi.mock('../lib/client.js', () => ({
9
- convexCallWithSession: (...args) => convexCallWithSessionMock(...args),
9
+ kernelCallWithSession: (...args) => kernelCallWithSessionMock(...args),
10
10
  }));
11
11
  vi.mock('../lib/config.js', () => ({
12
12
  getConfigOrGuide: vi.fn(() => Promise.resolve({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
@@ -19,11 +19,11 @@ describe('runRelate', () => {
19
19
  beforeEach(() => {
20
20
  vi.clearAllMocks();
21
21
  mockSession = { sessionId: 'sess-test' };
22
- convexCallWithSessionMock.mockResolvedValue({});
22
+ kernelCallWithSessionMock.mockResolvedValue({});
23
23
  });
24
24
  it('calls chain.createEntryRelation with correct args', async () => {
25
25
  await runRelate({ fromId: 'BET-151', type: 'informed_by', toId: 'DEC-264' });
26
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
26
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
27
27
  fromEntryId: 'BET-151',
28
28
  toEntryId: 'DEC-264',
29
29
  type: 'informed_by',
@@ -31,7 +31,7 @@ describe('runRelate', () => {
31
31
  });
32
32
  it('passes ifMissing=true when --if-missing flag is set', async () => {
33
33
  await runRelate({ fromId: 'BET-151', type: 'part_of', toId: 'FEAT-77', ifMissing: true });
34
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
34
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
35
35
  fromEntryId: 'BET-151',
36
36
  toEntryId: 'FEAT-77',
37
37
  type: 'part_of',
@@ -40,14 +40,14 @@ describe('runRelate', () => {
40
40
  });
41
41
  it('does not pass ifMissing when flag is not set', async () => {
42
42
  await runRelate({ fromId: 'BET-151', type: 'part_of', toId: 'FEAT-77' });
43
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
43
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
44
44
  fromEntryId: 'BET-151',
45
45
  toEntryId: 'FEAT-77',
46
46
  type: 'part_of',
47
47
  });
48
48
  });
49
49
  it('handles alreadyExists=true response gracefully and reflects it in output', async () => {
50
- convexCallWithSessionMock.mockResolvedValue({ alreadyExists: true });
50
+ kernelCallWithSessionMock.mockResolvedValue({ alreadyExists: true });
51
51
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
52
52
  await runRelate({ fromId: 'BET-151', type: 'part_of', toId: 'FEAT-77', ifMissing: true });
53
53
  const output = writeSpy.mock.calls.map(c => String(c[0])).join('');
@@ -56,7 +56,7 @@ describe('runRelate', () => {
56
56
  expect(output).toContain('alreadyExists');
57
57
  });
58
58
  it('surfaces proposal_created when backend returns a proposal instead of a relation', async () => {
59
- convexCallWithSessionMock.mockResolvedValue({
59
+ kernelCallWithSessionMock.mockResolvedValue({
60
60
  status: 'proposal_created',
61
61
  proposalId: 'prop-123',
62
62
  fromEntryId: 'STD-2',
@@ -73,22 +73,22 @@ describe('runRelate', () => {
73
73
  it('throws CLIError with no active session', async () => {
74
74
  mockSession = null;
75
75
  await expect(runRelate({ fromId: 'A', type: 'x', toId: 'B' })).rejects.toThrow('No active session');
76
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
76
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
77
77
  });
78
78
  it('throws CLIError with empty args', async () => {
79
79
  await expect(runRelate({ fromId: '', type: 'x', toId: 'B' })).rejects.toThrow('All arguments required');
80
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
80
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
81
81
  });
82
82
  });
83
83
  describe('runUnrelate', () => {
84
84
  beforeEach(() => {
85
85
  vi.clearAllMocks();
86
86
  mockSession = { sessionId: 'sess-test' };
87
- convexCallWithSessionMock.mockResolvedValue({});
87
+ kernelCallWithSessionMock.mockResolvedValue({});
88
88
  });
89
89
  it('calls chain.removeEntryRelation with correct args', async () => {
90
90
  await runUnrelate({ fromId: 'BET-151', type: 'part_of', toId: 'FEAT-77' });
91
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.removeEntryRelation', {
91
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.removeEntryRelation', {
92
92
  fromEntryId: 'BET-151',
93
93
  toEntryId: 'FEAT-77',
94
94
  type: 'part_of',
@@ -97,7 +97,7 @@ describe('runUnrelate', () => {
97
97
  it('throws CLIError with no active session', async () => {
98
98
  mockSession = null;
99
99
  await expect(runUnrelate({ fromId: 'A', type: 'x', toId: 'B' })).rejects.toThrow('No active session');
100
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
100
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
101
101
  });
102
102
  });
103
103
  //# sourceMappingURL=relate.test.js.map
@@ -1,13 +1,13 @@
1
1
  /**
2
- * session-touch — verify convexCallWithSession auto-renews the session TTL.
2
+ * session-touch — verify kernelCallWithSession auto-renews the session TTL.
3
3
  * BET-181 Slice 1: Session Auto-Renew on Write.
4
4
  *
5
5
  * Done-when criteria tested:
6
- * 1. After a successful convexCallWithSession, agent.touchSession is called with the current session ID
7
- * 2. Touch happens in exactly ONE place (convexCallWithSession) — not per-command
6
+ * 1. After a successful kernelCallWithSession, agent.touchSession is called with the current session ID
7
+ * 2. Touch happens in exactly ONE place (kernelCallWithSession) — not per-command
8
8
  * 3. Touch is fire-and-forget (does not block the write response)
9
9
  * 4. When no session is active (session.json absent), no touch is attempted
10
- * 5. When convexCallWithSession fails (write error), touch is NOT called
10
+ * 5. When kernelCallWithSession fails (write error), touch is NOT called
11
11
  */
12
12
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
13
13
  // We need to control what readSession() returns per test.
@@ -19,7 +19,7 @@ vi.mock('../lib/config.js', () => ({
19
19
  getConfig: vi.fn(() => ({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
20
20
  }));
21
21
  // Import the module under test AFTER setting up mocks.
22
- import { convexCallWithSession } from '../lib/client.js';
22
+ import { kernelCallWithSession } from '../lib/client.js';
23
23
  // Helper: build a fetch mock that returns different responses based on `fn`.
24
24
  function makeFetch({ writeOk = true, writeData = { ok: true }, } = {}) {
25
25
  return vi.fn(async (_input, init) => {
@@ -43,7 +43,7 @@ async function flushMicrotasks() {
43
43
  await Promise.resolve();
44
44
  await Promise.resolve();
45
45
  }
46
- describe('convexCallWithSession — session touch on write', () => {
46
+ describe('kernelCallWithSession — session touch on write', () => {
47
47
  beforeEach(() => {
48
48
  vi.clearAllMocks();
49
49
  mockSession = {
@@ -59,7 +59,7 @@ describe('convexCallWithSession — session touch on write', () => {
59
59
  });
60
60
  it('calls agent.touchSession with the current session ID after a successful write', async () => {
61
61
  global.fetch = makeFetch({ writeOk: true, writeData: { entryId: 'BET-181' } });
62
- await convexCallWithSession('chain.updateEntry', { entryId: 'BET-181', name: 'New name' });
62
+ await kernelCallWithSession('chain.updateEntry', { entryId: 'BET-181', name: 'New name' });
63
63
  await flushMicrotasks();
64
64
  const calls = global.fetch.mock.calls;
65
65
  // Expect exactly 2 fetch calls: the write + the touch
@@ -75,7 +75,7 @@ describe('convexCallWithSession — session touch on write', () => {
75
75
  it('does NOT call agent.touchSession when no session is active', async () => {
76
76
  mockSession = null;
77
77
  global.fetch = makeFetch({ writeOk: true });
78
- await convexCallWithSession('chain.updateEntry', { entryId: 'BET-100' });
78
+ await kernelCallWithSession('chain.updateEntry', { entryId: 'BET-100' });
79
79
  await flushMicrotasks();
80
80
  const calls = global.fetch.mock.calls;
81
81
  // Only the write call — no touch
@@ -85,7 +85,7 @@ describe('convexCallWithSession — session touch on write', () => {
85
85
  });
86
86
  it('does NOT call agent.touchSession when the write fails', async () => {
87
87
  global.fetch = makeFetch({ writeOk: false });
88
- await expect(convexCallWithSession('chain.updateEntry', { entryId: 'BET-100' })).rejects.toThrow('Server error');
88
+ await expect(kernelCallWithSession('chain.updateEntry', { entryId: 'BET-100' })).rejects.toThrow('Server error');
89
89
  await flushMicrotasks();
90
90
  const calls = global.fetch.mock.calls;
91
91
  // Only the write call — no touch because write threw
@@ -106,7 +106,7 @@ describe('convexCallWithSession — session touch on write', () => {
106
106
  };
107
107
  });
108
108
  // Should resolve successfully despite touch throwing
109
- const result = await convexCallWithSession('chain.updateEntry', { entryId: 'BET-181' });
109
+ const result = await kernelCallWithSession('chain.updateEntry', { entryId: 'BET-181' });
110
110
  await flushMicrotasks();
111
111
  expect(result).toEqual({ entryId: 'BET-181' });
112
112
  });
@@ -123,7 +123,7 @@ describe('convexCallWithSession — session touch on write', () => {
123
123
  order.push('write-complete');
124
124
  return { ok: true, json: async () => ({ data: { entryId: 'BET-181' } }) };
125
125
  });
126
- await convexCallWithSession('chain.updateEntry', { entryId: 'BET-181' });
126
+ await kernelCallWithSession('chain.updateEntry', { entryId: 'BET-181' });
127
127
  // Write has resolved — touch has NOT yet completed (it's still pending)
128
128
  expect(order).toEqual(['write-complete']);
129
129
  // After waiting for the touch to finish
@@ -5,8 +5,8 @@
5
5
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
6
  import { runSessionId } from '../commands/session.js';
7
7
  vi.mock('../lib/client.js', () => ({
8
- convexCall: vi.fn(),
9
- convexCallWithSession: vi.fn(),
8
+ kernelCall: vi.fn(),
9
+ kernelCallWithSession: vi.fn(),
10
10
  }));
11
11
  vi.mock('../lib/config.js', () => ({
12
12
  getConfigOrGuide: vi.fn(() => Promise.resolve({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
@@ -14,11 +14,11 @@ vi.mock('../lib/telemetry.js', () => ({
14
14
  },
15
15
  initTelemetry: vi.fn(),
16
16
  }));
17
- const convexCallMock = vi.fn();
18
- const convexCallWithSessionMock = vi.fn();
17
+ const kernelCallMock = vi.fn();
18
+ const kernelCallWithSessionMock = vi.fn();
19
19
  vi.mock('../lib/client.js', () => ({
20
- convexCall: (...args) => convexCallMock(...args),
21
- convexCallWithSession: (...args) => convexCallWithSessionMock(...args),
20
+ kernelCall: (...args) => kernelCallMock(...args),
21
+ kernelCallWithSession: (...args) => kernelCallWithSessionMock(...args),
22
22
  }));
23
23
  let mockConfig = {
24
24
  apiKey: 'pb_sk_test_key_1234',
@@ -85,7 +85,7 @@ describe('runSetup', () => {
85
85
  mockSession = null;
86
86
  });
87
87
  it('skips login when valid config exists and runs onboarding', async () => {
88
- convexCallMock.mockResolvedValueOnce({ _id: 'ws-1', keyId: 'key-1', name: 'Test Workspace' }); // resolveWorkspace
88
+ kernelCallMock.mockResolvedValueOnce({ _id: 'ws-1', keyId: 'key-1', name: 'Test Workspace' }); // resolveWorkspace
89
89
  const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
90
90
  await runSetup();
91
91
  // Should NOT call runLogin
@@ -118,7 +118,7 @@ describe('runSetup', () => {
118
118
  runLoginMock.mockImplementation(() => {
119
119
  mockConfig = { apiKey: 'pb_sk_new_key', siteUrl: 'https://test.convex.site' };
120
120
  });
121
- convexCallMock.mockResolvedValueOnce({ _id: 'ws-1', keyId: 'key-1', name: 'Test Workspace' }); // resolveWorkspace
121
+ kernelCallMock.mockResolvedValueOnce({ _id: 'ws-1', keyId: 'key-1', name: 'Test Workspace' }); // resolveWorkspace
122
122
  const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
123
123
  await runSetup();
124
124
  expect(runLoginMock).toHaveBeenCalledOnce();
@@ -128,7 +128,7 @@ describe('runSetup', () => {
128
128
  logSpy.mockRestore();
129
129
  });
130
130
  it('handles workspace verification failure gracefully', async () => {
131
- convexCallMock.mockRejectedValueOnce(new Error('Network error')); // resolveWorkspace fails
131
+ kernelCallMock.mockRejectedValueOnce(new Error('Network error')); // resolveWorkspace fails
132
132
  const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
133
133
  await runSetup();
134
134
  // Should warn about connection
@@ -1,15 +1,15 @@
1
1
  /**
2
- * pb update — verify convexCallWithSession sequence and args.
2
+ * pb update — verify kernelCallWithSession sequence and args.
3
3
  * TEN-341 test contract: happy path, no session, empty entryId.
4
4
  */
5
5
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
6
  import { runUpdate } from '../commands/update.js';
7
7
  import { CLIError } from '../lib/errors.js';
8
- const convexCallWithSessionMock = vi.fn();
9
- const convexCallMock = vi.fn();
8
+ const kernelCallWithSessionMock = vi.fn();
9
+ const kernelCallMock = vi.fn();
10
10
  vi.mock('../lib/client.js', () => ({
11
- convexCallWithSession: (...args) => convexCallWithSessionMock(...args),
12
- convexCall: (...args) => convexCallMock(...args),
11
+ kernelCallWithSession: (...args) => kernelCallWithSessionMock(...args),
12
+ kernelCall: (...args) => kernelCallMock(...args),
13
13
  // McpError exported so update.ts can import the type (not used at runtime in tests).
14
14
  McpError: class McpError extends Error {
15
15
  details;
@@ -50,7 +50,7 @@ describe('runUpdate', () => {
50
50
  vi.clearAllMocks();
51
51
  mockSession = { sessionId: 'sess-test' };
52
52
  // BET-192: updateEntry returns warnings + normalization breakdown (symmetric with createEntry)
53
- convexCallWithSessionMock.mockResolvedValue({
53
+ kernelCallWithSessionMock.mockResolvedValue({
54
54
  id: 'j571abc123def456',
55
55
  warnings: [],
56
56
  normalization: { remapped: {}, rejected: [], accepted: [] },
@@ -58,7 +58,7 @@ describe('runUpdate', () => {
58
58
  validationWarnings: [],
59
59
  });
60
60
  // Post-update refresh: default to returning a minimal entry.
61
- convexCallMock.mockResolvedValue({
61
+ kernelCallMock.mockResolvedValue({
62
62
  entryId: 'BET-151',
63
63
  name: 'Test Entry',
64
64
  status: 'active',
@@ -72,7 +72,7 @@ describe('runUpdate', () => {
72
72
  note: 'Updated description',
73
73
  });
74
74
  writeSpy.mockRestore();
75
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
75
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
76
76
  entryId: 'BET-151',
77
77
  changedBy: 'agent:sess-test',
78
78
  data: { description: 'new description' },
@@ -88,7 +88,7 @@ describe('runUpdate', () => {
88
88
  note: 'Resolved',
89
89
  });
90
90
  writeSpy.mockRestore();
91
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
91
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
92
92
  entryId: 'TEN-703',
93
93
  changedBy: 'agent:sess-test',
94
94
  name: 'New name',
@@ -103,7 +103,7 @@ describe('runUpdate', () => {
103
103
  workflowStatus: 'shipped',
104
104
  });
105
105
  writeSpy.mockRestore();
106
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
106
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
107
107
  entryId: 'BET-271',
108
108
  changedBy: 'agent:sess-test',
109
109
  workflowStatus: 'shipped',
@@ -116,7 +116,7 @@ describe('runUpdate', () => {
116
116
  field: ['rationale=a=b=c'],
117
117
  });
118
118
  writeSpy.mockRestore();
119
- expect(convexCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
119
+ expect(kernelCallWithSessionMock).toHaveBeenCalledWith('chain.updateEntry', {
120
120
  entryId: 'DEC-264',
121
121
  changedBy: 'agent:sess-test',
122
122
  data: { rationale: 'a=b=c' },
@@ -126,21 +126,21 @@ describe('runUpdate', () => {
126
126
  mockSession = null;
127
127
  await expect(runUpdate({ entryId: 'BET-151', field: ['x=1'] })).rejects.toThrow(CLIError);
128
128
  await expect(runUpdate({ entryId: 'BET-151', field: ['x=1'] })).rejects.toThrow('No active session');
129
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
129
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
130
130
  });
131
131
  it('throws CLIError with empty entryId', async () => {
132
132
  await expect(runUpdate({ entryId: ' ', field: ['x=1'] })).rejects.toThrow(CLIError);
133
133
  await expect(runUpdate({ entryId: ' ', field: ['x=1'] })).rejects.toThrow('Entry ID is required');
134
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
134
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
135
135
  });
136
136
  it('throws CLIError when nothing to update', async () => {
137
137
  await expect(runUpdate({ entryId: 'BET-151' })).rejects.toThrow(CLIError);
138
138
  await expect(runUpdate({ entryId: 'BET-151' })).rejects.toThrow('Nothing to update');
139
- expect(convexCallWithSessionMock).not.toHaveBeenCalled();
139
+ expect(kernelCallWithSessionMock).not.toHaveBeenCalled();
140
140
  });
141
141
  // ── Structured validation error tests ────────────────────────────────────
142
142
  it('throws CLIError with structured select field error message', async () => {
143
- convexCallWithSessionMock.mockRejectedValue(makeMcpError("Entry data validation failed: Field \"appetite\" must be one of: small, medium, large. Got: 'Small Batch'. Fix the values and try again.", 'VALIDATION_FAILED', [{
143
+ kernelCallWithSessionMock.mockRejectedValue(makeMcpError("Entry data validation failed: Field \"appetite\" must be one of: small, medium, large. Got: 'Small Batch'. Fix the values and try again.", 'VALIDATION_FAILED', [{
144
144
  fieldKey: 'appetite',
145
145
  fieldLabel: 'appetite',
146
146
  invalidValue: 'Small Batch',
@@ -154,14 +154,14 @@ describe('runUpdate', () => {
154
154
  expect(err.message).toContain("Got: 'Small Batch'");
155
155
  });
156
156
  it('throws CLIError with plain error message when no structured details', async () => {
157
- convexCallWithSessionMock.mockRejectedValue(makeMcpError('Entry not found.', 'NOT_FOUND'));
157
+ kernelCallWithSessionMock.mockRejectedValue(makeMcpError('Entry not found.', 'NOT_FOUND'));
158
158
  const err = await runUpdate({ entryId: 'BET-999', field: ['x=1'] }).catch((e) => e);
159
159
  expect(err).toBeInstanceOf(CLIError);
160
160
  expect(err.message).toContain('Entry not found.');
161
161
  });
162
162
  // ── Slice 3: post-update refresh ─────────────────────────────────────────
163
163
  it('calls chain.getEntry after successful update and includes entry in output', async () => {
164
- convexCallMock.mockResolvedValue({
164
+ kernelCallMock.mockResolvedValue({
165
165
  entryId: 'BET-151',
166
166
  name: 'My Bet',
167
167
  status: 'active',
@@ -170,13 +170,13 @@ describe('runUpdate', () => {
170
170
  await runUpdate({ entryId: 'BET-151', field: ['description=new'] });
171
171
  const output = writeSpy.mock.calls.map(c => String(c[0])).join('');
172
172
  writeSpy.mockRestore();
173
- expect(convexCallMock).toHaveBeenCalledWith('chain.getEntry', { entryId: 'BET-151' });
173
+ expect(kernelCallMock).toHaveBeenCalledWith('chain.getEntry', { entryId: 'BET-151' });
174
174
  // Pretty output: receipt then entry block
175
175
  expect(output).toContain('Updated BET-151');
176
176
  expect(output).toContain('My Bet');
177
177
  });
178
178
  it('still shows update receipt when post-update getEntry fails (graceful degradation)', async () => {
179
- convexCallMock.mockRejectedValue(new Error('network error'));
179
+ kernelCallMock.mockRejectedValue(new Error('network error'));
180
180
  const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
181
181
  await runUpdate({ entryId: 'BET-151', field: ['description=new'] });
182
182
  const output = writeSpy.mock.calls.map(c => String(c[0])).join('');
@@ -187,7 +187,7 @@ describe('runUpdate', () => {
187
187
  });
188
188
  // ── BET-192 / FEAT-575: Normalization warning tests ──────────────────────
189
189
  it('throws CLIError when fields are rejected (BET-192, BET-271)', async () => {
190
- convexCallWithSessionMock.mockResolvedValue({
190
+ kernelCallWithSessionMock.mockResolvedValue({
191
191
  id: 'j571abc123def456',
192
192
  warnings: ['Unknown field "foo" dropped. Available fields: description, doneWhen'],
193
193
  normalization: { remapped: {}, rejected: ['foo'], accepted: ['description'] },
@@ -207,7 +207,7 @@ describe('runUpdate', () => {
207
207
  writeSpy.mockRestore();
208
208
  });
209
209
  it('displays no warnings when all fields are valid (BET-192)', async () => {
210
- convexCallWithSessionMock.mockResolvedValue({
210
+ kernelCallWithSessionMock.mockResolvedValue({
211
211
  id: 'j571abc123def456',
212
212
  warnings: [],
213
213
  normalization: { remapped: {}, rejected: [], accepted: ['description'] },