@productbrain/cli 0.1.0-beta.92 → 0.1.0-beta.95
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/dist/__tests__/authority-domains.test.d.ts +2 -0
- package/dist/__tests__/authority-domains.test.d.ts.map +1 -0
- package/dist/__tests__/authority-domains.test.js +45 -0
- package/dist/__tests__/authority-domains.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +1 -1
- package/dist/__tests__/config.test.js +139 -9
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/envelope-contract.test.d.ts +15 -0
- package/dist/__tests__/envelope-contract.test.d.ts.map +1 -0
- package/dist/__tests__/envelope-contract.test.js +126 -0
- package/dist/__tests__/envelope-contract.test.js.map +1 -0
- package/dist/__tests__/handshake-preview.test.js +123 -0
- package/dist/__tests__/handshake-preview.test.js.map +1 -1
- package/dist/__tests__/profiles.test.js +38 -5
- package/dist/__tests__/profiles.test.js.map +1 -1
- package/dist/__tests__/setup-ingest.test.d.ts +2 -0
- package/dist/__tests__/setup-ingest.test.d.ts.map +1 -0
- package/dist/__tests__/setup-ingest.test.js +55 -0
- package/dist/__tests__/setup-ingest.test.js.map +1 -0
- package/dist/__tests__/setup-resolver.test.d.ts +14 -0
- package/dist/__tests__/setup-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/setup-resolver.test.js +228 -0
- package/dist/__tests__/setup-resolver.test.js.map +1 -0
- package/dist/commands/authority-domains.d.ts +122 -0
- package/dist/commands/authority-domains.d.ts.map +1 -0
- package/dist/commands/authority-domains.js +235 -0
- package/dist/commands/authority-domains.js.map +1 -0
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +29 -9
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connect.test.js +47 -0
- package/dist/commands/connect.test.js.map +1 -1
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +188 -3
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/migrate-setup.d.ts +18 -0
- package/dist/commands/migrate-setup.d.ts.map +1 -0
- package/dist/commands/migrate-setup.js +198 -0
- package/dist/commands/migrate-setup.js.map +1 -0
- package/dist/commands/profile.d.ts +24 -1
- package/dist/commands/profile.d.ts.map +1 -1
- package/dist/commands/profile.js +72 -6
- package/dist/commands/profile.js.map +1 -1
- package/dist/commands/session.js +5 -5
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/setup-ingest.d.ts +17 -0
- package/dist/commands/setup-ingest.d.ts.map +1 -0
- package/dist/commands/setup-ingest.js +224 -0
- package/dist/commands/setup-ingest.js.map +1 -0
- package/dist/commands/setup-resolver.d.ts +58 -0
- package/dist/commands/setup-resolver.d.ts.map +1 -0
- package/dist/commands/setup-resolver.js +150 -0
- package/dist/commands/setup-resolver.js.map +1 -0
- package/dist/commands/workspace.d.ts +51 -0
- package/dist/commands/workspace.d.ts.map +1 -1
- package/dist/commands/workspace.js +24 -0
- package/dist/commands/workspace.js.map +1 -1
- package/dist/formatters/orient.d.ts +25 -0
- package/dist/formatters/orient.d.ts.map +1 -1
- package/dist/formatters/orient.js +16 -0
- package/dist/formatters/orient.js.map +1 -1
- package/dist/index.js +105 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/canonicalRefs.d.ts +43 -0
- package/dist/lib/canonicalRefs.d.ts.map +1 -0
- package/dist/lib/canonicalRefs.js +83 -0
- package/dist/lib/canonicalRefs.js.map +1 -0
- package/dist/lib/client.js +16 -16
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/config.d.ts +32 -9
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +93 -46
- package/dist/lib/config.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authority-domains.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/authority-domains.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { formatAuthorityDomainProposalRun } from '../commands/authority-domains.js';
|
|
3
|
+
describe('formatAuthorityDomainProposalRun', () => {
|
|
4
|
+
it('renders dry-run proposal evidence without implying writes', () => {
|
|
5
|
+
const output = formatAuthorityDomainProposalRun({
|
|
6
|
+
runId: 'wp354-domain-proposals-test',
|
|
7
|
+
dryRun: true,
|
|
8
|
+
processed: 2,
|
|
9
|
+
tagged: 1,
|
|
10
|
+
skipped: 1,
|
|
11
|
+
errors: 0,
|
|
12
|
+
relationsCreated: 0,
|
|
13
|
+
relationsAlreadyExisted: 0,
|
|
14
|
+
preview: [
|
|
15
|
+
{
|
|
16
|
+
sourceEntryId: 'STD-101',
|
|
17
|
+
sourceName: 'Single Source of Truth',
|
|
18
|
+
sourceCollectionSlug: 'standards',
|
|
19
|
+
sourceCanonicalKey: 'standard',
|
|
20
|
+
domainEntryId: 'DOMAIN-ARCHITECTURE',
|
|
21
|
+
domainName: 'Architecture',
|
|
22
|
+
proposedDomainSlug: 'architecture',
|
|
23
|
+
confidence: 0.91,
|
|
24
|
+
reasoning: 'Proposed architecture because the entry governs durable system design.',
|
|
25
|
+
decisionRightReason: 'Proposed architecture because the entry governs durable system design.',
|
|
26
|
+
sourceSignals: ['architecture: schema and system-boundary language'],
|
|
27
|
+
rejectedAlternatives: [
|
|
28
|
+
{ slug: 'governance', reason: 'Lower authority-right score than selected candidate.' },
|
|
29
|
+
],
|
|
30
|
+
classifierVersion: 'wp354-authority-domain-classifier-v1',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
notes: ['Deterministic heuristic proposal generation used; no LLM call was made.'],
|
|
34
|
+
});
|
|
35
|
+
expect(output).toContain('Dry run: yes');
|
|
36
|
+
expect(output).toContain('Dry-run preview');
|
|
37
|
+
expect(output).toContain('No staging rows or graph relations were written.');
|
|
38
|
+
expect(output).toContain('STD-101 -> architecture (91%)');
|
|
39
|
+
expect(output).toContain('Source: Single Source of Truth [standards/standard]');
|
|
40
|
+
expect(output).toContain('Reason: Proposed architecture because the entry governs durable system design.');
|
|
41
|
+
expect(output).toContain('Signals: architecture: schema and system-boundary language');
|
|
42
|
+
expect(output).toContain('Rejected: governance (Lower authority-right score than selected candidate.)');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=authority-domains.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authority-domains.test.js","sourceRoot":"","sources":["../../src/__tests__/authority-domains.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gCAAgC,EAAE,MAAM,kCAAkC,CAAC;AAEpF,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,MAAM,GAAG,gCAAgC,CAAC;YAC9C,KAAK,EAAE,6BAA6B;YACpC,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,CAAC;YACT,gBAAgB,EAAE,CAAC;YACnB,uBAAuB,EAAE,CAAC;YAC1B,OAAO,EAAE;gBACP;oBACE,aAAa,EAAE,SAAS;oBACxB,UAAU,EAAE,wBAAwB;oBACpC,oBAAoB,EAAE,WAAW;oBACjC,kBAAkB,EAAE,UAAU;oBAC9B,aAAa,EAAE,qBAAqB;oBACpC,UAAU,EAAE,cAAc;oBAC1B,kBAAkB,EAAE,cAAc;oBAClC,UAAU,EAAE,IAAI;oBAChB,SAAS,EAAE,wEAAwE;oBACnF,mBAAmB,EAAE,wEAAwE;oBAC7F,aAAa,EAAE,CAAC,mDAAmD,CAAC;oBACpE,oBAAoB,EAAE;wBACpB,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,sDAAsD,EAAE;qBACvF;oBACD,iBAAiB,EAAE,sCAAsC;iBAC1D;aACF;YACD,KAAK,EAAE,CAAC,yEAAyE,CAAC;SACnF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAC;QAC7E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qDAAqD,CAAC,CAAC;QAChF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gFAAgF,CAAC,CAAC;QAC3G,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,4DAA4D,CAAC,CAAC;QACvF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,6EAA6E,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for config resolution — WP-303 Slice 0.
|
|
3
3
|
*
|
|
4
|
-
* Tests resolveConfig(), getConfigSafe(), and
|
|
4
|
+
* Tests resolveConfig(), getConfigSafe(), findProjectRoot(), and config file reading.
|
|
5
5
|
* Uses temp directories and mocks to isolate from real config on the filesystem.
|
|
6
6
|
*/
|
|
7
7
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for config resolution — WP-303 Slice 0.
|
|
3
3
|
*
|
|
4
|
-
* Tests resolveConfig(), getConfigSafe(), and
|
|
4
|
+
* Tests resolveConfig(), getConfigSafe(), findProjectRoot(), and config file reading.
|
|
5
5
|
* Uses temp directories and mocks to isolate from real config on the filesystem.
|
|
6
6
|
*/
|
|
7
7
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
@@ -12,6 +12,7 @@ import { randomUUID } from 'crypto';
|
|
|
12
12
|
// Mock the profiles module to prevent real profile config from leaking in
|
|
13
13
|
vi.mock('../lib/profiles.js', () => ({
|
|
14
14
|
resolveProfileConfig: vi.fn(() => null),
|
|
15
|
+
resolveNamedProfileConfig: vi.fn(() => null),
|
|
15
16
|
}));
|
|
16
17
|
// Mock os.homedir to prevent reading real ~/.config/productbrain/.env
|
|
17
18
|
vi.mock('os', async (importOriginal) => {
|
|
@@ -30,7 +31,10 @@ describe('config resolution', () => {
|
|
|
30
31
|
let resolveConfig;
|
|
31
32
|
let getConfigSafe;
|
|
32
33
|
let resetConfigCache;
|
|
34
|
+
let findProjectRoot;
|
|
33
35
|
beforeEach(async () => {
|
|
36
|
+
// Reset all mocks first to prevent queued mockReturnValueOnce state leakage between tests
|
|
37
|
+
vi.resetAllMocks();
|
|
34
38
|
// Save and clear relevant env vars
|
|
35
39
|
for (const key of envKeys) {
|
|
36
40
|
savedEnv[key] = process.env[key];
|
|
@@ -46,6 +50,7 @@ describe('config resolution', () => {
|
|
|
46
50
|
resolveConfig = config.resolveConfig;
|
|
47
51
|
getConfigSafe = config.getConfigSafe;
|
|
48
52
|
resetConfigCache = config.resetConfigCache;
|
|
53
|
+
findProjectRoot = config.findProjectRoot;
|
|
49
54
|
// Reset envLoaded state before each test
|
|
50
55
|
resetConfigCache();
|
|
51
56
|
});
|
|
@@ -69,22 +74,98 @@ describe('config resolution', () => {
|
|
|
69
74
|
// ignore
|
|
70
75
|
}
|
|
71
76
|
});
|
|
77
|
+
describe('findProjectRoot()', () => {
|
|
78
|
+
it('finds .productbrain/ in the start directory', () => {
|
|
79
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
80
|
+
mkdirSync(pbDir, { recursive: true });
|
|
81
|
+
const result = findProjectRoot(tempDir);
|
|
82
|
+
expect(result).toBe(tempDir);
|
|
83
|
+
});
|
|
84
|
+
it('finds .productbrain/ in a parent directory', () => {
|
|
85
|
+
// Create .productbrain/ in tempDir
|
|
86
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
87
|
+
mkdirSync(pbDir, { recursive: true });
|
|
88
|
+
// Create a subdirectory and search from there
|
|
89
|
+
const subDir = resolve(tempDir, 'src', 'commands');
|
|
90
|
+
mkdirSync(subDir, { recursive: true });
|
|
91
|
+
const result = findProjectRoot(subDir);
|
|
92
|
+
expect(result).toBe(tempDir);
|
|
93
|
+
});
|
|
94
|
+
it('returns null when no .productbrain/ found up to home', () => {
|
|
95
|
+
// tempDir is under the real system tmpdir. The mocked homedir() returns a
|
|
96
|
+
// path that is NOT an ancestor of tempDir, so the walk will exhaust all
|
|
97
|
+
// ancestors of tempDir up to the filesystem root and return null because
|
|
98
|
+
// neither tempDir nor any ancestor has .productbrain/ AND the mocked home
|
|
99
|
+
// is never reached (it's a sibling branch, not a parent).
|
|
100
|
+
// We use a fresh subdir under tempDir so there is definitely no .productbrain/.
|
|
101
|
+
const searchDir = resolve(tempDir, 'no-pb-here', 'subdir');
|
|
102
|
+
mkdirSync(searchDir, { recursive: true });
|
|
103
|
+
const result = findProjectRoot(searchDir);
|
|
104
|
+
expect(result).toBeNull();
|
|
105
|
+
});
|
|
106
|
+
it('stops walking at the home directory', () => {
|
|
107
|
+
// The mocked homedir() returns a fake path outside tempDir.
|
|
108
|
+
// Create a fresh dir inside tempDir (no .productbrain/ present).
|
|
109
|
+
// findProjectRoot will walk up from it, never find .productbrain/,
|
|
110
|
+
// and eventually stop — returning null.
|
|
111
|
+
const deepDir = resolve(tempDir, 'deeply', 'nested', 'project');
|
|
112
|
+
mkdirSync(deepDir, { recursive: true });
|
|
113
|
+
const result = findProjectRoot(deepDir);
|
|
114
|
+
expect(result).toBeNull();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
72
117
|
describe('resolveConfig()', () => {
|
|
73
|
-
it('returns project config.json values when env vars
|
|
118
|
+
it('returns project config.local.json profile values when env vars absent', async () => {
|
|
119
|
+
const { resolveNamedProfileConfig } = await import('../lib/profiles.js');
|
|
120
|
+
resolveNamedProfileConfig.mockReturnValueOnce({
|
|
121
|
+
apiKey: 'pb_sk_local_profile_key',
|
|
122
|
+
siteUrl: 'https://local-profile.example.com',
|
|
123
|
+
});
|
|
74
124
|
const pbDir = resolve(tempDir, '.productbrain');
|
|
75
125
|
mkdirSync(pbDir, { recursive: true });
|
|
76
|
-
writeFileSync(resolve(pbDir, 'config.json'), JSON.stringify({
|
|
126
|
+
writeFileSync(resolve(pbDir, 'config.local.json'), JSON.stringify({ profile: 'my-workspace' }));
|
|
77
127
|
const result = resolveConfig();
|
|
78
|
-
expect(result.apiKey).toBe('
|
|
79
|
-
expect(result.siteUrl).toBe('https://
|
|
128
|
+
expect(result.apiKey).toBe('pb_sk_local_profile_key');
|
|
129
|
+
expect(result.siteUrl).toBe('https://local-profile.example.com');
|
|
80
130
|
expect(result.source).toBe('project');
|
|
81
131
|
});
|
|
82
|
-
it('
|
|
132
|
+
it('config.local.json profile beats global profile', async () => {
|
|
133
|
+
const { resolveNamedProfileConfig, resolveProfileConfig } = await import('../lib/profiles.js');
|
|
134
|
+
resolveNamedProfileConfig.mockReturnValueOnce({
|
|
135
|
+
apiKey: 'pb_sk_local_profile_key',
|
|
136
|
+
siteUrl: 'https://local-profile.example.com',
|
|
137
|
+
});
|
|
138
|
+
resolveProfileConfig.mockReturnValueOnce({
|
|
139
|
+
apiKey: 'pb_sk_global_profile_key',
|
|
140
|
+
siteUrl: 'https://global-profile.example.com',
|
|
141
|
+
});
|
|
142
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
143
|
+
mkdirSync(pbDir, { recursive: true });
|
|
144
|
+
writeFileSync(resolve(pbDir, 'config.local.json'), JSON.stringify({ profile: 'local-workspace' }));
|
|
145
|
+
const result = resolveConfig();
|
|
146
|
+
expect(result.apiKey).toBe('pb_sk_local_profile_key');
|
|
147
|
+
expect(result.source).toBe('project');
|
|
148
|
+
});
|
|
149
|
+
it('config.json siteUrl is used as gateway override with global profile', async () => {
|
|
150
|
+
const { resolveProfileConfig } = await import('../lib/profiles.js');
|
|
151
|
+
resolveProfileConfig.mockReturnValueOnce({
|
|
152
|
+
apiKey: 'pb_sk_global_key',
|
|
153
|
+
siteUrl: 'https://profile.example.com',
|
|
154
|
+
});
|
|
155
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
156
|
+
mkdirSync(pbDir, { recursive: true });
|
|
157
|
+
writeFileSync(resolve(pbDir, 'config.json'), JSON.stringify({ siteUrl: 'https://project-gateway.example.com' }));
|
|
158
|
+
const result = resolveConfig();
|
|
159
|
+
expect(result.apiKey).toBe('pb_sk_global_key');
|
|
160
|
+
expect(result.siteUrl).toBe('https://project-gateway.example.com');
|
|
161
|
+
expect(result.source).toBe('profile');
|
|
162
|
+
});
|
|
163
|
+
it('env vars override project config.local.json', () => {
|
|
83
164
|
process.env.PRODUCTBRAIN_API_KEY = 'pb_sk_env_key';
|
|
84
165
|
process.env.CONVEX_SITE_URL = 'https://env.example.com';
|
|
85
166
|
const pbDir = resolve(tempDir, '.productbrain');
|
|
86
167
|
mkdirSync(pbDir, { recursive: true });
|
|
87
|
-
writeFileSync(resolve(pbDir, 'config.json'), JSON.stringify({
|
|
168
|
+
writeFileSync(resolve(pbDir, 'config.local.json'), JSON.stringify({ profile: 'some-workspace' }));
|
|
88
169
|
const result = resolveConfig();
|
|
89
170
|
expect(result.apiKey).toBe('pb_sk_env_key');
|
|
90
171
|
expect(result.siteUrl).toBe('https://env.example.com');
|
|
@@ -96,6 +177,16 @@ describe('config resolution', () => {
|
|
|
96
177
|
expect(result.siteUrl).toBe('https://gateway.productbrain.io');
|
|
97
178
|
expect(result.source).toBe('default');
|
|
98
179
|
});
|
|
180
|
+
it('ignores profile field in config.json (legacy migration)', () => {
|
|
181
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
182
|
+
mkdirSync(pbDir, { recursive: true });
|
|
183
|
+
// Old config.json with profile field — must be ignored
|
|
184
|
+
writeFileSync(resolve(pbDir, 'config.json'), JSON.stringify({ siteUrl: 'https://project.example.com', profile: 'should-be-ignored' }));
|
|
185
|
+
const result = resolveConfig();
|
|
186
|
+
// profile in config.json must NOT be resolved — no profile mock set up
|
|
187
|
+
expect(result.apiKey).toBeUndefined();
|
|
188
|
+
expect(result.source).toBe('default');
|
|
189
|
+
});
|
|
99
190
|
it('handles partial project config (only siteUrl, no apiKey)', () => {
|
|
100
191
|
const pbDir = resolve(tempDir, '.productbrain');
|
|
101
192
|
mkdirSync(pbDir, { recursive: true });
|
|
@@ -127,10 +218,15 @@ describe('config resolution', () => {
|
|
|
127
218
|
expect(result.source).toBe('env');
|
|
128
219
|
}
|
|
129
220
|
});
|
|
130
|
-
it('returns { ok: true } with project source when key in config.json', () => {
|
|
221
|
+
it('returns { ok: true } with project source when key in config.local.json profile', async () => {
|
|
222
|
+
const { resolveNamedProfileConfig } = await import('../lib/profiles.js');
|
|
223
|
+
resolveNamedProfileConfig.mockReturnValueOnce({
|
|
224
|
+
apiKey: 'pb_sk_proj_safe',
|
|
225
|
+
siteUrl: 'https://proj.example.com',
|
|
226
|
+
});
|
|
131
227
|
const pbDir = resolve(tempDir, '.productbrain');
|
|
132
228
|
mkdirSync(pbDir, { recursive: true });
|
|
133
|
-
writeFileSync(resolve(pbDir, 'config.json'), JSON.stringify({
|
|
229
|
+
writeFileSync(resolve(pbDir, 'config.local.json'), JSON.stringify({ profile: 'test-workspace' }));
|
|
134
230
|
resetConfigCache();
|
|
135
231
|
const result = getConfigSafe();
|
|
136
232
|
expect(result.ok).toBe(true);
|
|
@@ -155,6 +251,20 @@ describe('config resolution', () => {
|
|
|
155
251
|
expect(result.source).toBe('default');
|
|
156
252
|
stderrWrite.mockRestore();
|
|
157
253
|
});
|
|
254
|
+
it('warns but does not crash on invalid config.local.json', () => {
|
|
255
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
256
|
+
mkdirSync(pbDir, { recursive: true });
|
|
257
|
+
writeFileSync(resolve(pbDir, 'config.local.json'), '{ invalid json!!!');
|
|
258
|
+
// Capture stderr
|
|
259
|
+
const stderrWrite = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
260
|
+
const result = resolveConfig();
|
|
261
|
+
// Should have warned about config.local.json
|
|
262
|
+
expect(stderrWrite).toHaveBeenCalledWith(expect.stringContaining('invalid JSON'));
|
|
263
|
+
// Should fall through to default
|
|
264
|
+
expect(result.apiKey).toBeUndefined();
|
|
265
|
+
expect(result.source).toBe('default');
|
|
266
|
+
stderrWrite.mockRestore();
|
|
267
|
+
});
|
|
158
268
|
it('skips gracefully when config.json is missing', () => {
|
|
159
269
|
// No .productbrain directory at all
|
|
160
270
|
const result = resolveConfig();
|
|
@@ -162,5 +272,25 @@ describe('config resolution', () => {
|
|
|
162
272
|
expect(result.source).toBe('default');
|
|
163
273
|
});
|
|
164
274
|
});
|
|
275
|
+
describe('directory walking', () => {
|
|
276
|
+
it('resolveConfig reads config.local.json from a parent directory', async () => {
|
|
277
|
+
const { resolveNamedProfileConfig } = await import('../lib/profiles.js');
|
|
278
|
+
resolveNamedProfileConfig.mockReturnValueOnce({
|
|
279
|
+
apiKey: 'pb_sk_parent_key',
|
|
280
|
+
siteUrl: 'https://parent.example.com',
|
|
281
|
+
});
|
|
282
|
+
// Create .productbrain in tempDir
|
|
283
|
+
const pbDir = resolve(tempDir, '.productbrain');
|
|
284
|
+
mkdirSync(pbDir, { recursive: true });
|
|
285
|
+
writeFileSync(resolve(pbDir, 'config.local.json'), JSON.stringify({ profile: 'parent-workspace' }));
|
|
286
|
+
// Set CWD to a subdirectory
|
|
287
|
+
const subDir = resolve(tempDir, 'src', 'lib');
|
|
288
|
+
mkdirSync(subDir, { recursive: true });
|
|
289
|
+
process.cwd = () => subDir;
|
|
290
|
+
const result = resolveConfig();
|
|
291
|
+
expect(result.apiKey).toBe('pb_sk_parent_key');
|
|
292
|
+
expect(result.source).toBe('project');
|
|
293
|
+
});
|
|
294
|
+
});
|
|
165
295
|
});
|
|
166
296
|
//# sourceMappingURL=config.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-surface envelope contract — CLI side (WP-321 E6 S9).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors packages/mcp-server/src/__tests__/envelope-contract.test.ts.
|
|
5
|
+
* Together they prove the same gateway bytes work correctly for both surfaces.
|
|
6
|
+
*
|
|
7
|
+
* CLI contract:
|
|
8
|
+
* kernelCall / kernelCallWithSession extract envelope.data from HTTP responses.
|
|
9
|
+
* ok:false or non-200 → throw McpError.
|
|
10
|
+
*
|
|
11
|
+
* Same mock HTTP response is used here as in the MCP envelope-contract test,
|
|
12
|
+
* proving both surfaces consume the same gateway bytes correctly (WP-321 done-when).
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=envelope-contract.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-contract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/envelope-contract.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-surface envelope contract — CLI side (WP-321 E6 S9).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors packages/mcp-server/src/__tests__/envelope-contract.test.ts.
|
|
5
|
+
* Together they prove the same gateway bytes work correctly for both surfaces.
|
|
6
|
+
*
|
|
7
|
+
* CLI contract:
|
|
8
|
+
* kernelCall / kernelCallWithSession extract envelope.data from HTTP responses.
|
|
9
|
+
* ok:false or non-200 → throw McpError.
|
|
10
|
+
*
|
|
11
|
+
* Same mock HTTP response is used here as in the MCP envelope-contract test,
|
|
12
|
+
* proving both surfaces consume the same gateway bytes correctly (WP-321 done-when).
|
|
13
|
+
*/
|
|
14
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
15
|
+
// ─── Module mocks (must precede imports that trigger side effects) ────────────
|
|
16
|
+
vi.mock('../lib/config.js', () => ({
|
|
17
|
+
getConfig: vi.fn(() => ({
|
|
18
|
+
apiKey: 'pb_sk_test',
|
|
19
|
+
siteUrl: 'https://example.convex.site',
|
|
20
|
+
})),
|
|
21
|
+
resolveAdminConfig: vi.fn(),
|
|
22
|
+
}));
|
|
23
|
+
vi.mock('../lib/session.js', () => ({
|
|
24
|
+
readSession: vi.fn(() => null),
|
|
25
|
+
writeSession: vi.fn(),
|
|
26
|
+
clearSession: vi.fn(),
|
|
27
|
+
addCapturedEntry: vi.fn(),
|
|
28
|
+
}));
|
|
29
|
+
vi.mock('../lib/spinner.js', () => ({
|
|
30
|
+
withSpinner: vi.fn((_label, fn) => fn()),
|
|
31
|
+
}));
|
|
32
|
+
// ─── Imports (after mocks) ────────────────────────────────────────────────────
|
|
33
|
+
import { kernelCall, kernelCallWithSession, McpError } from '../lib/client.js';
|
|
34
|
+
function makeSuccessResponse(body, status = 200) {
|
|
35
|
+
return {
|
|
36
|
+
ok: status >= 200 && status < 300,
|
|
37
|
+
status,
|
|
38
|
+
statusText: 'OK',
|
|
39
|
+
json: async () => body,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function makeErrorResponse(body, status) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
status,
|
|
46
|
+
statusText: 'Error',
|
|
47
|
+
json: async () => body,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function installFetch(response) {
|
|
51
|
+
global.fetch = vi.fn().mockResolvedValue(response);
|
|
52
|
+
}
|
|
53
|
+
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
54
|
+
describe("CLI envelope contract — kernelCall", () => {
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
vi.clearAllMocks();
|
|
57
|
+
});
|
|
58
|
+
it("success: extracts data from ok:true envelope", async () => {
|
|
59
|
+
// Same gateway bytes as MCP envelope-contract test
|
|
60
|
+
installFetch(makeSuccessResponse({
|
|
61
|
+
ok: true,
|
|
62
|
+
summary: "Orient complete",
|
|
63
|
+
data: { entries: [] },
|
|
64
|
+
next: [{ tool: "capture", description: "Capture next", parameters: {} }],
|
|
65
|
+
_meta: { durationMs: 42 },
|
|
66
|
+
}));
|
|
67
|
+
const data = await kernelCall("chain.getOrientEntries", { workspaceId: "ws-1" });
|
|
68
|
+
// CLI extracts only data — agent summary/next/meta are not passed to CLI callers
|
|
69
|
+
expect(data).toEqual({ entries: [] });
|
|
70
|
+
});
|
|
71
|
+
it("success without next: data field is correctly extracted", async () => {
|
|
72
|
+
installFetch(makeSuccessResponse({
|
|
73
|
+
ok: true,
|
|
74
|
+
summary: "Done",
|
|
75
|
+
data: { id: "ENT-1" },
|
|
76
|
+
}));
|
|
77
|
+
const data = await kernelCall("chain.getEntry", { entryId: "ENT-1" });
|
|
78
|
+
expect(data).toEqual({ id: "ENT-1" });
|
|
79
|
+
});
|
|
80
|
+
it("error: non-200 HTTP throws McpError with kernel message", async () => {
|
|
81
|
+
installFetch(makeErrorResponse({
|
|
82
|
+
ok: false,
|
|
83
|
+
code: "NOT_FOUND",
|
|
84
|
+
message: "Entry not found",
|
|
85
|
+
}, 404));
|
|
86
|
+
await expect(kernelCall("chain.getEntry", { entryId: "ENT-MISSING" })).rejects.toThrow(McpError);
|
|
87
|
+
await expect(kernelCall("chain.getEntry", { entryId: "ENT-MISSING" })).rejects.toSatisfy((err) => {
|
|
88
|
+
if (!(err instanceof McpError))
|
|
89
|
+
return false;
|
|
90
|
+
return err.message.includes("Entry not found");
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
it("error: ok:false at HTTP 200 throws McpError (forward-compat for DEC-571)", async () => {
|
|
94
|
+
// DEC-571: gateway returns ok:false at HTTP 200 for soft failures
|
|
95
|
+
installFetch(makeSuccessResponse({
|
|
96
|
+
ok: false,
|
|
97
|
+
code: "VALIDATION_FAILED",
|
|
98
|
+
message: "Required field missing",
|
|
99
|
+
}, 200));
|
|
100
|
+
await expect(kernelCall("chain.capture", { name: "" })).rejects.toThrow(McpError);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe("CLI envelope contract — kernelCallWithSession", () => {
|
|
104
|
+
beforeEach(() => {
|
|
105
|
+
vi.clearAllMocks();
|
|
106
|
+
});
|
|
107
|
+
it("success: extracts data from ok:true envelope (same as kernelCall)", async () => {
|
|
108
|
+
installFetch(makeSuccessResponse({
|
|
109
|
+
ok: true,
|
|
110
|
+
summary: "Entry created",
|
|
111
|
+
data: { entryId: "BET-99", name: "Test bet" },
|
|
112
|
+
_meta: { durationMs: 100 },
|
|
113
|
+
}));
|
|
114
|
+
const data = await kernelCallWithSession("agentKnowledge.captureEnvelope", { name: "Test bet" });
|
|
115
|
+
expect(data).toEqual({ entryId: "BET-99", name: "Test bet" });
|
|
116
|
+
});
|
|
117
|
+
it("error: ok:false with HTTP 200 throws McpError (same as kernelCall)", async () => {
|
|
118
|
+
installFetch(makeSuccessResponse({
|
|
119
|
+
ok: false,
|
|
120
|
+
code: "COMMIT_BLOCKED",
|
|
121
|
+
message: "Strategy link missing",
|
|
122
|
+
}, 200));
|
|
123
|
+
await expect(kernelCallWithSession("agentKnowledge.captureEnvelope", { name: "" })).rejects.toThrow(McpError);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=envelope-contract.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-contract.test.js","sourceRoot":"","sources":["../../src/__tests__/envelope-contract.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -104,6 +104,8 @@ vi.mock('../lib/method-registry.js', () => ({
|
|
|
104
104
|
}));
|
|
105
105
|
import { writeFileSync } from 'fs';
|
|
106
106
|
import { formatHandshakeReport } from '../formatters/handshake.js';
|
|
107
|
+
import { kernelCall } from '../lib/client.js';
|
|
108
|
+
import { generateCursorSkill, shouldEmitToTarget } from '../generators/portable-knowledge.js';
|
|
107
109
|
import { runHandshake } from '../commands/handshake.js';
|
|
108
110
|
function capturedReport() {
|
|
109
111
|
const calls = vi.mocked(formatHandshakeReport).mock.calls;
|
|
@@ -152,5 +154,126 @@ describe('runHandshake — preview/apply/dryRun invariants (WP-332 S1)', () => {
|
|
|
152
154
|
const entry = report?.previewPlan?.find((e) => e.path.includes('AGENTS.md') && e.status === 'forked');
|
|
153
155
|
expect(entry).toBeDefined();
|
|
154
156
|
});
|
|
157
|
+
it('apply mode projects DB setup assets with body-derived refs, disabled filtering, and hash trailers', async () => {
|
|
158
|
+
vi.mocked(shouldEmitToTarget).mockImplementation((_entry, target) => target === 'cursor');
|
|
159
|
+
vi.mocked(generateCursorSkill).mockImplementation((skill) => skill.body);
|
|
160
|
+
vi.mocked(kernelCall).mockImplementation(async (tool, args) => {
|
|
161
|
+
if (tool === 'chain.workspaceReadiness')
|
|
162
|
+
return null;
|
|
163
|
+
if (tool === 'chain.getOrientView')
|
|
164
|
+
return null;
|
|
165
|
+
if (tool === 'chain.searchEntries')
|
|
166
|
+
return [];
|
|
167
|
+
if (tool === 'setup.listAssetsForUser') {
|
|
168
|
+
return [
|
|
169
|
+
{
|
|
170
|
+
entryId: 'SETUP-SKILL-NO-REFS',
|
|
171
|
+
name: 'No Refs',
|
|
172
|
+
description: 'No ref skill',
|
|
173
|
+
body: '# No refs\nPlain body.',
|
|
174
|
+
triggers: [],
|
|
175
|
+
assetKind: 'skill',
|
|
176
|
+
semanticRefs: [],
|
|
177
|
+
disabledByOwner: false,
|
|
178
|
+
lastProjectedHash: null,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
entryId: 'SETUP-SKILL-WITH-REF',
|
|
182
|
+
name: 'With Ref',
|
|
183
|
+
description: 'Ref skill',
|
|
184
|
+
body: '# With ref\nUse {{ref:entry:WP-345}}.',
|
|
185
|
+
triggers: [],
|
|
186
|
+
assetKind: 'skill',
|
|
187
|
+
semanticRefs: ['entry:WP-345'],
|
|
188
|
+
disabledByOwner: false,
|
|
189
|
+
lastProjectedHash: null,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
entryId: 'SETUP-SKILL-DISABLED',
|
|
193
|
+
name: 'Disabled Skill',
|
|
194
|
+
description: 'Disabled',
|
|
195
|
+
body: '# Disabled',
|
|
196
|
+
triggers: [],
|
|
197
|
+
assetKind: 'skill',
|
|
198
|
+
semanticRefs: [],
|
|
199
|
+
disabledByOwner: true,
|
|
200
|
+
lastProjectedHash: null,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
entryId: 'SETUP-BUNDLE-DEMO',
|
|
204
|
+
name: 'Bundle Demo',
|
|
205
|
+
description: 'Bundle',
|
|
206
|
+
body: '# Bundle',
|
|
207
|
+
triggers: [],
|
|
208
|
+
assetKind: 'bundle',
|
|
209
|
+
semanticRefs: [],
|
|
210
|
+
disabledByOwner: false,
|
|
211
|
+
lastProjectedHash: null,
|
|
212
|
+
},
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
if (tool === 'setup.resolveSemanticRefs') {
|
|
216
|
+
expect(args?.semanticRefs).toEqual(['entry:WP-345']);
|
|
217
|
+
return [{ ref: 'entry:WP-345', resolved: { entryId: 'WP-345', name: 'Dynamic Skills' } }];
|
|
218
|
+
}
|
|
219
|
+
if (tool === 'setup.updateLastProjectedHash')
|
|
220
|
+
return { ok: true };
|
|
221
|
+
if (tool === 'setup.materializeSetup')
|
|
222
|
+
return { ok: true, assetCount: 2, receiptWritten: true };
|
|
223
|
+
return [];
|
|
224
|
+
});
|
|
225
|
+
await runHandshake({ apply: true, surfaces: ['cursor'] });
|
|
226
|
+
const writes = vi.mocked(writeFileSync).mock.calls.map(([path, content]) => ({
|
|
227
|
+
path: String(path),
|
|
228
|
+
content: String(content),
|
|
229
|
+
}));
|
|
230
|
+
const noRefs = writes.find((w) => w.path.endsWith('/.cursor/skills/No Refs/SKILL.md'));
|
|
231
|
+
const withRef = writes.find((w) => w.path.endsWith('/.cursor/skills/With Ref/SKILL.md'));
|
|
232
|
+
expect(noRefs?.content).toContain('Plain body.');
|
|
233
|
+
expect(noRefs?.content).toContain('<!-- pb-hash: sha256:');
|
|
234
|
+
expect(withRef?.content).toContain('Use {{ref:entry:WP-345}}.');
|
|
235
|
+
expect(withRef?.content).toContain('<!-- pb-hash: sha256:');
|
|
236
|
+
expect(writes.some((w) => w.path.includes('Disabled Skill'))).toBe(false);
|
|
237
|
+
expect(writes.some((w) => w.path.includes('Bundle Demo'))).toBe(false);
|
|
238
|
+
const hashUpdates = vi.mocked(kernelCall).mock.calls.filter(([tool]) => tool === 'setup.updateLastProjectedHash');
|
|
239
|
+
expect(hashUpdates).toHaveLength(2);
|
|
240
|
+
expect(hashUpdates.map(([, args]) => args.entryId).sort()).toEqual([
|
|
241
|
+
'SETUP-SKILL-NO-REFS',
|
|
242
|
+
'SETUP-SKILL-WITH-REF',
|
|
243
|
+
]);
|
|
244
|
+
});
|
|
245
|
+
it('does not update lastProjectedHash when a DB asset projection is forked and skipped', async () => {
|
|
246
|
+
vi.mocked(shouldEmitToTarget).mockImplementation((_entry, target) => target === 'cursor');
|
|
247
|
+
vi.mocked(generateCursorSkill).mockImplementation((skill) => skill.body);
|
|
248
|
+
vi.mocked(kernelCall).mockImplementation(async (tool) => {
|
|
249
|
+
if (tool === 'chain.workspaceReadiness')
|
|
250
|
+
return null;
|
|
251
|
+
if (tool === 'chain.getOrientView')
|
|
252
|
+
return null;
|
|
253
|
+
if (tool === 'chain.searchEntries')
|
|
254
|
+
return [];
|
|
255
|
+
if (tool === 'setup.listAssetsForUser') {
|
|
256
|
+
return [
|
|
257
|
+
{
|
|
258
|
+
entryId: 'SETUP-SKILL-FORKED',
|
|
259
|
+
name: 'Forked Skill',
|
|
260
|
+
description: 'Forked',
|
|
261
|
+
body: '# Forked\nBody.',
|
|
262
|
+
triggers: [],
|
|
263
|
+
assetKind: 'skill',
|
|
264
|
+
semanticRefs: [],
|
|
265
|
+
disabledByOwner: false,
|
|
266
|
+
lastProjectedHash: null,
|
|
267
|
+
},
|
|
268
|
+
];
|
|
269
|
+
}
|
|
270
|
+
if (tool === 'setup.materializeSetup')
|
|
271
|
+
return { ok: true, assetCount: 1, receiptWritten: true };
|
|
272
|
+
return [];
|
|
273
|
+
});
|
|
274
|
+
vfs[`${MOCK_CWD}/.cursor/skills/Forked Skill/SKILL.md`] = '# User fork\nNo generated marker.';
|
|
275
|
+
await runHandshake({ apply: true, surfaces: ['cursor'] });
|
|
276
|
+
expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.updateLastProjectedHash')).toBe(false);
|
|
277
|
+
});
|
|
155
278
|
});
|
|
156
279
|
//# sourceMappingURL=handshake-preview.test.js.map
|