@productbrain/cli 0.1.0-beta.7 → 0.1.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -1
- package/dist/__tests__/capture.test.d.ts +2 -0
- package/dist/__tests__/capture.test.d.ts.map +1 -0
- package/dist/__tests__/capture.test.js +86 -0
- package/dist/__tests__/capture.test.js.map +1 -0
- package/dist/__tests__/constellation.test.d.ts +2 -0
- package/dist/__tests__/constellation.test.d.ts.map +1 -0
- package/dist/__tests__/constellation.test.js +260 -0
- package/dist/__tests__/constellation.test.js.map +1 -0
- package/dist/__tests__/fields.test.d.ts +2 -0
- package/dist/__tests__/fields.test.d.ts.map +1 -0
- package/dist/__tests__/fields.test.js +238 -0
- package/dist/__tests__/fields.test.js.map +1 -0
- package/dist/__tests__/handshake.test.d.ts +2 -0
- package/dist/__tests__/handshake.test.d.ts.map +1 -0
- package/dist/__tests__/handshake.test.js +187 -0
- package/dist/__tests__/handshake.test.js.map +1 -0
- package/dist/__tests__/relate.test.d.ts +2 -0
- package/dist/__tests__/relate.test.d.ts.map +1 -0
- package/dist/__tests__/relate.test.js +79 -0
- package/dist/__tests__/relate.test.js.map +1 -0
- package/dist/__tests__/repo-detect.test.d.ts +2 -0
- package/dist/__tests__/repo-detect.test.d.ts.map +1 -0
- package/dist/__tests__/repo-detect.test.js +119 -0
- package/dist/__tests__/repo-detect.test.js.map +1 -0
- package/dist/__tests__/runner.test.d.ts +2 -0
- package/dist/__tests__/runner.test.d.ts.map +1 -0
- package/dist/__tests__/runner.test.js +215 -0
- package/dist/__tests__/runner.test.js.map +1 -0
- package/dist/__tests__/session-touch.test.d.ts +2 -0
- package/dist/__tests__/session-touch.test.d.ts.map +1 -0
- package/dist/__tests__/session-touch.test.js +134 -0
- package/dist/__tests__/session-touch.test.js.map +1 -0
- package/dist/__tests__/session.test.d.ts +2 -0
- package/dist/__tests__/session.test.d.ts.map +1 -0
- package/dist/__tests__/session.test.js +52 -0
- package/dist/__tests__/session.test.js.map +1 -0
- package/dist/__tests__/strip.test.d.ts +2 -0
- package/dist/__tests__/strip.test.d.ts.map +1 -0
- package/dist/__tests__/strip.test.js +136 -0
- package/dist/__tests__/strip.test.js.map +1 -0
- package/dist/__tests__/update.test.d.ts +2 -0
- package/dist/__tests__/update.test.d.ts.map +1 -0
- package/dist/__tests__/update.test.js +148 -0
- package/dist/__tests__/update.test.js.map +1 -0
- package/dist/commands/capture.d.ts +21 -0
- package/dist/commands/capture.d.ts.map +1 -0
- package/dist/commands/capture.js +100 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/constellation.d.ts +11 -0
- package/dist/commands/constellation.d.ts.map +1 -0
- package/dist/commands/constellation.js +28 -0
- package/dist/commands/constellation.js.map +1 -0
- package/dist/commands/context.d.ts +2 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +15 -9
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/fields.d.ts +9 -0
- package/dist/commands/fields.d.ts.map +1 -0
- package/dist/commands/fields.js +26 -0
- package/dist/commands/fields.js.map +1 -0
- package/dist/commands/get.d.ts +8 -1
- package/dist/commands/get.d.ts.map +1 -1
- package/dist/commands/get.js +51 -6
- package/dist/commands/get.js.map +1 -1
- package/dist/commands/handshake.d.ts +18 -0
- package/dist/commands/handshake.d.ts.map +1 -0
- package/dist/commands/handshake.js +378 -0
- package/dist/commands/handshake.js.map +1 -0
- package/dist/commands/ingest.d.ts +1 -0
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +25 -8
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/orient.d.ts +1 -0
- package/dist/commands/orient.d.ts.map +1 -1
- package/dist/commands/orient.js +13 -8
- package/dist/commands/orient.js.map +1 -1
- package/dist/commands/relate.d.ts +15 -0
- package/dist/commands/relate.d.ts.map +1 -0
- package/dist/commands/relate.js +72 -0
- package/dist/commands/relate.js.map +1 -0
- package/dist/commands/search.d.ts +1 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +5 -3
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session.d.ts +20 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +134 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/update.d.ts +16 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +89 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/formatters/capture.d.ts +30 -0
- package/dist/formatters/capture.d.ts.map +1 -0
- package/dist/formatters/capture.js +58 -0
- package/dist/formatters/capture.js.map +1 -0
- package/dist/formatters/constellation.d.ts +34 -0
- package/dist/formatters/constellation.d.ts.map +1 -0
- package/dist/formatters/constellation.js +38 -0
- package/dist/formatters/constellation.js.map +1 -0
- package/dist/formatters/fields.d.ts +32 -0
- package/dist/formatters/fields.d.ts.map +1 -0
- package/dist/formatters/fields.js +49 -0
- package/dist/formatters/fields.js.map +1 -0
- package/dist/formatters/handshake.d.ts +17 -0
- package/dist/formatters/handshake.d.ts.map +1 -0
- package/dist/formatters/handshake.js +51 -0
- package/dist/formatters/handshake.js.map +1 -0
- package/dist/formatters/relate.d.ts +11 -0
- package/dist/formatters/relate.d.ts.map +1 -0
- package/dist/formatters/relate.js +10 -0
- package/dist/formatters/relate.js.map +1 -0
- package/dist/formatters/session.d.ts +11 -0
- package/dist/formatters/session.d.ts.map +1 -0
- package/dist/formatters/session.js +51 -0
- package/dist/formatters/session.js.map +1 -0
- package/dist/formatters/update.d.ts +17 -0
- package/dist/formatters/update.d.ts.map +1 -0
- package/dist/formatters/update.js +43 -0
- package/dist/formatters/update.js.map +1 -0
- package/dist/generators/adapters.d.ts +10 -0
- package/dist/generators/adapters.d.ts.map +1 -0
- package/dist/generators/adapters.js +102 -0
- package/dist/generators/adapters.js.map +1 -0
- package/dist/generators/briefing-md.d.ts +8 -0
- package/dist/generators/briefing-md.d.ts.map +1 -0
- package/dist/generators/briefing-md.js +51 -0
- package/dist/generators/briefing-md.js.map +1 -0
- package/dist/generators/context-md.d.ts +8 -0
- package/dist/generators/context-md.d.ts.map +1 -0
- package/dist/generators/context-md.js +123 -0
- package/dist/generators/context-md.js.map +1 -0
- package/dist/generators/portable-knowledge.d.ts +72 -0
- package/dist/generators/portable-knowledge.d.ts.map +1 -0
- package/dist/generators/portable-knowledge.js +246 -0
- package/dist/generators/portable-knowledge.js.map +1 -0
- package/dist/generators/portable-knowledge.test.d.ts +2 -0
- package/dist/generators/portable-knowledge.test.d.ts.map +1 -0
- package/dist/generators/portable-knowledge.test.js +399 -0
- package/dist/generators/portable-knowledge.test.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +231 -6
- package/dist/index.js.map +1 -1
- package/dist/lib/client.d.ts +19 -0
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +102 -8
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/repo-detect.d.ts +14 -0
- package/dist/lib/repo-detect.d.ts.map +1 -0
- package/dist/lib/repo-detect.js +58 -0
- package/dist/lib/repo-detect.js.map +1 -0
- package/dist/lib/runner.d.ts +31 -0
- package/dist/lib/runner.d.ts.map +1 -0
- package/dist/lib/runner.js +65 -0
- package/dist/lib/runner.js.map +1 -0
- package/dist/lib/session.d.ts +17 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/session.js +43 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/strip.d.ts +11 -0
- package/dist/lib/strip.d.ts.map +1 -0
- package/dist/lib/strip.js +26 -0
- package/dist/lib/strip.js.map +1 -0
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Product Brain CLI (`pb`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CLI for Chain knowledge: read, search, gather context, and **write back**. Uses your Product Brain API key (same as MCP). Write commands require a readwrite key.
|
|
4
4
|
|
|
5
5
|
**Requirements:** Node 18+, API key from Product Brain → Settings → API Keys (`pb_sk_*`).
|
|
6
6
|
|
|
@@ -48,12 +48,95 @@ Config is read from (in order): env vars → `~/.config/productbrain/.env` → `
|
|
|
48
48
|
|
|
49
49
|
## Commands
|
|
50
50
|
|
|
51
|
+
### Read (no session required)
|
|
52
|
+
|
|
51
53
|
| Command | Description |
|
|
52
54
|
|--------|-------------|
|
|
53
55
|
| `pb orient` | Workspace stage, bets, governance, tensions. Use `-b` for a brief view. |
|
|
54
56
|
| `pb search <query>` | Full-text search across the Chain. |
|
|
55
57
|
| `pb get <entry-id>` | Full entry (data, relations, last 10 history events). |
|
|
56
58
|
| `pb context <entry-id>` | Constellation context (pipe-friendly markdown when not a TTY). |
|
|
59
|
+
| `pb handshake` | Generate context files for AI developer tools. See below. |
|
|
57
60
|
| `pb login` | Save your API key to `~/.config/productbrain/.env`. |
|
|
58
61
|
|
|
62
|
+
### Write (session required — DEC-9)
|
|
63
|
+
|
|
64
|
+
| Command | Description |
|
|
65
|
+
|--------|-------------|
|
|
66
|
+
| `pb session start` | Open a tracked write session. Refreshes context files. |
|
|
67
|
+
| `pb capture "<text>"` | Capture a decision, tension, insight, or any knowledge to the Chain. Auto-classifies. |
|
|
68
|
+
| `pb session close` | Close the session. Shows captured entries, runs wrapup, refreshes context. |
|
|
69
|
+
|
|
59
70
|
`pb --help` for options.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## `pb handshake` — AI Developer Onboarding
|
|
75
|
+
|
|
76
|
+
One command generates context files for every major AI coding tool:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pb handshake
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**What it generates:**
|
|
83
|
+
|
|
84
|
+
| File | Purpose |
|
|
85
|
+
|------|---------|
|
|
86
|
+
| `.productbrain/context.md` | Workspace briefing — stage, bets, governance, architecture, tensions |
|
|
87
|
+
| `.productbrain/briefing.md` | Chain entries matched to this specific repo |
|
|
88
|
+
| `CLAUDE.md` | Adapter for Claude Code |
|
|
89
|
+
| `.cursor/rules/chain.mdc` | Adapter for Cursor |
|
|
90
|
+
| `.github/copilot-instructions.md` | Adapter for GitHub Copilot |
|
|
91
|
+
|
|
92
|
+
**Options:**
|
|
93
|
+
|
|
94
|
+
- `--force` — Overwrite adapter files even if they have custom content
|
|
95
|
+
- `--dry-run` — Preview what would be generated without writing files
|
|
96
|
+
|
|
97
|
+
**Safety:** Adapter files are marked with `auto-generated by pb handshake`. If you customize one and remove the marker, future runs skip it (unless `--force`). The `.productbrain/` directory contains workspace-specific context and should be in `.gitignore`.
|
|
98
|
+
|
|
99
|
+
**Governance:** Context export surface per DEC-161 and GLO-63. Architecture: ARCH-63 (surfaces are peers consuming the kernel).
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## `pb session` + `pb capture` — Close the Loop
|
|
104
|
+
|
|
105
|
+
The Chain compounds from every AI coding session. Instead of knowledge dying in chat transcripts (TEN-27), capture it as you work.
|
|
106
|
+
|
|
107
|
+
### Flow
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Start of session
|
|
111
|
+
pb session start # opens session, refreshes context
|
|
112
|
+
|
|
113
|
+
# During work — capture what you learn
|
|
114
|
+
pb capture "TEN: topology query returns stale containers when initiatives are archived"
|
|
115
|
+
pb capture "DEC: excluded archived initiatives at the query level, not the UI filter"
|
|
116
|
+
pb capture "INS: learned that the containerIds array references soft-deleted entries"
|
|
117
|
+
|
|
118
|
+
# End of session
|
|
119
|
+
pb session close # shows summary, runs wrapup, refreshes context
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### How capture works
|
|
123
|
+
|
|
124
|
+
1. Text is sent to the Chain's classification pipeline — auto-assigns collection
|
|
125
|
+
2. Entry is created as a **draft** (nothing auto-commits)
|
|
126
|
+
3. Receipt shows: entry ID, collection, confidence, reasoning, alternatives
|
|
127
|
+
4. You review and commit drafts in Product Brain Studio
|
|
128
|
+
|
|
129
|
+
### Options
|
|
130
|
+
|
|
131
|
+
- `pb capture --collection tensions "text"` — skip auto-classification, use explicit collection
|
|
132
|
+
- `pb capture --name "Short title" --description "Full explanation"` — separate name and description
|
|
133
|
+
- `pb session close --force` — clear local session state even if server close fails
|
|
134
|
+
|
|
135
|
+
### Governance
|
|
136
|
+
|
|
137
|
+
- Write access requires a tracked session (DEC-9, BR-8)
|
|
138
|
+
- Session attribution via API key; `clientKind: 'cli'` discriminator per DEC-184 (pending schema extension)
|
|
139
|
+
- All captures are drafts — human reviews and commits (TEN-374)
|
|
140
|
+
- Solves TEN-264 (CLI write access session attribution) with explicit session token in `.productbrain/session.json`
|
|
141
|
+
- Addresses TEN-27 (strategic conversations generate decisions that never reach the Chain)
|
|
142
|
+
- Implements INS-80 (proactive capture during coding)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/capture.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pb capture extensions — --link, --json flags.
|
|
3
|
+
* TEN-341 test contract: capture --link calls createEntryRelation, capture --json outputs JSON.
|
|
4
|
+
*/
|
|
5
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import { runCapture } from '../commands/capture.js';
|
|
7
|
+
const mcpCallWithSessionMock = vi.fn();
|
|
8
|
+
vi.mock('../lib/client.js', () => ({
|
|
9
|
+
mcpCallWithSession: (...args) => mcpCallWithSessionMock(...args),
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('../lib/config.js', () => ({
|
|
12
|
+
getConfigOrGuide: vi.fn(() => Promise.resolve({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
|
|
13
|
+
}));
|
|
14
|
+
let mockSession = { sessionId: 'sess-test' };
|
|
15
|
+
vi.mock('../lib/session.js', () => ({
|
|
16
|
+
readSession: () => mockSession,
|
|
17
|
+
addCapturedEntry: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
describe('runCapture --link', () => {
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
mcpCallWithSessionMock.mockReset();
|
|
22
|
+
mockSession = { sessionId: 'sess-test' };
|
|
23
|
+
});
|
|
24
|
+
it('creates entry then links to target with default relation type', async () => {
|
|
25
|
+
mcpCallWithSessionMock
|
|
26
|
+
.mockResolvedValueOnce({ collection: 'tensions', confidence: 0.9, tier: 'high' })
|
|
27
|
+
.mockResolvedValueOnce({ docId: 'doc-1', entryId: 'TEN-710' })
|
|
28
|
+
.mockResolvedValueOnce({});
|
|
29
|
+
const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
30
|
+
await runCapture({ text: 'TEN: missing validation', link: 'BET-151' });
|
|
31
|
+
expect(mcpCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
|
|
32
|
+
fromEntryId: 'TEN-710',
|
|
33
|
+
toEntryId: 'BET-151',
|
|
34
|
+
type: 'surfaces_tension_in',
|
|
35
|
+
});
|
|
36
|
+
writeSpy.mockRestore();
|
|
37
|
+
});
|
|
38
|
+
it('uses custom relation type when --type provided', async () => {
|
|
39
|
+
mcpCallWithSessionMock
|
|
40
|
+
.mockResolvedValueOnce({ collection: 'insights', confidence: 0.8, tier: 'high' })
|
|
41
|
+
.mockResolvedValueOnce({ docId: 'doc-2', entryId: 'INS-50' })
|
|
42
|
+
.mockResolvedValueOnce({});
|
|
43
|
+
const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
44
|
+
await runCapture({ text: 'INS: discovered X', link: 'DEC-264', type: 'informed_by' });
|
|
45
|
+
expect(mcpCallWithSessionMock).toHaveBeenCalledWith('chain.createEntryRelation', {
|
|
46
|
+
fromEntryId: 'INS-50',
|
|
47
|
+
toEntryId: 'DEC-264',
|
|
48
|
+
type: 'informed_by',
|
|
49
|
+
});
|
|
50
|
+
writeSpy.mockRestore();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('runCapture --json', () => {
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
mcpCallWithSessionMock.mockReset();
|
|
56
|
+
mockSession = { sessionId: 'sess-test' };
|
|
57
|
+
});
|
|
58
|
+
it('outputs valid JSON with id field and no other stdout', async () => {
|
|
59
|
+
mcpCallWithSessionMock
|
|
60
|
+
.mockResolvedValueOnce({ collection: 'tensions', confidence: 0.9, tier: 'high' })
|
|
61
|
+
.mockResolvedValueOnce({ docId: 'doc-1', entryId: 'TEN-711' });
|
|
62
|
+
let stdoutOutput = '';
|
|
63
|
+
const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => {
|
|
64
|
+
stdoutOutput += String(chunk);
|
|
65
|
+
return true;
|
|
66
|
+
});
|
|
67
|
+
await runCapture({ text: 'TEN: test', json: true });
|
|
68
|
+
writeSpy.mockRestore();
|
|
69
|
+
// Find JSON lines in stdout
|
|
70
|
+
const jsonLines = stdoutOutput.split('\n').filter(line => {
|
|
71
|
+
try {
|
|
72
|
+
JSON.parse(line);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
expect(jsonLines).toHaveLength(1);
|
|
80
|
+
const output = JSON.parse(jsonLines[0]);
|
|
81
|
+
expect(output).toHaveProperty('id', 'TEN-711');
|
|
82
|
+
expect(output).toHaveProperty('collection', 'tensions');
|
|
83
|
+
expect(output).toHaveProperty('confidence');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=capture.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.test.js","sourceRoot":"","sources":["../../src/__tests__/capture.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constellation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/constellation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pb constellation — unit tests.
|
|
3
|
+
* BET-181 Slice 3: compound view (entry + grouped relations).
|
|
4
|
+
*
|
|
5
|
+
* Verifies:
|
|
6
|
+
* 1. Mock mcpCall returns known constellation structure; command outputs entry + grouped relations
|
|
7
|
+
* 2. Edge: entry with no relations returns entry-only, empty relations object
|
|
8
|
+
* 3. Relation types in output derive from the server response, not hardcoded
|
|
9
|
+
*/
|
|
10
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
11
|
+
import { runConstellation } from '../commands/constellation.js';
|
|
12
|
+
import { setOutputMode } from '../lib/runner.js';
|
|
13
|
+
const mcpCallMock = vi.fn();
|
|
14
|
+
vi.mock('../lib/client.js', () => ({
|
|
15
|
+
mcpCall: (...args) => mcpCallMock(...args),
|
|
16
|
+
}));
|
|
17
|
+
vi.mock('../lib/config.js', () => ({
|
|
18
|
+
getConfigOrGuide: vi.fn((_fn) => Promise.resolve({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' })),
|
|
19
|
+
}));
|
|
20
|
+
// A known constellation fixture for BET-181
|
|
21
|
+
const CONSTELLATION_FIXTURE = {
|
|
22
|
+
entry: {
|
|
23
|
+
entryId: 'BET-181',
|
|
24
|
+
name: 'CLI Agent-Native Foundation',
|
|
25
|
+
collectionSlug: 'bets',
|
|
26
|
+
collectionName: 'Bets',
|
|
27
|
+
status: 'active',
|
|
28
|
+
},
|
|
29
|
+
relations: {
|
|
30
|
+
part_of: [
|
|
31
|
+
{
|
|
32
|
+
entryId: 'FEAT-100',
|
|
33
|
+
name: 'Product Brain CLI',
|
|
34
|
+
collectionSlug: 'features',
|
|
35
|
+
collectionName: 'Features',
|
|
36
|
+
direction: 'outgoing',
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
informed_by: [
|
|
40
|
+
{
|
|
41
|
+
entryId: 'DEC-299',
|
|
42
|
+
name: 'JSON default for agent-native output',
|
|
43
|
+
collectionSlug: 'decisions',
|
|
44
|
+
collectionName: 'Decisions',
|
|
45
|
+
direction: 'incoming',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
entryId: 'STD-65',
|
|
49
|
+
name: 'Structured, parseable, minimal',
|
|
50
|
+
collectionSlug: 'standards',
|
|
51
|
+
collectionName: 'Standards',
|
|
52
|
+
direction: 'incoming',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
summary: {
|
|
57
|
+
totalRelations: 3,
|
|
58
|
+
relationTypes: ['part_of', 'informed_by'],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
let stdoutOutput;
|
|
62
|
+
let stderrOutput;
|
|
63
|
+
let stdoutWriteSpy;
|
|
64
|
+
let stderrWriteSpy;
|
|
65
|
+
function withTty(isTty, fn) {
|
|
66
|
+
return async () => {
|
|
67
|
+
const original = process.stdout.isTTY;
|
|
68
|
+
Object.defineProperty(process.stdout, 'isTTY', { value: isTty, configurable: true, writable: true });
|
|
69
|
+
try {
|
|
70
|
+
await fn();
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
Object.defineProperty(process.stdout, 'isTTY', { value: original, configurable: true, writable: true });
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
beforeEach(() => {
|
|
78
|
+
stdoutOutput = '';
|
|
79
|
+
stderrOutput = '';
|
|
80
|
+
stdoutWriteSpy = vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => {
|
|
81
|
+
stdoutOutput += String(chunk);
|
|
82
|
+
return true;
|
|
83
|
+
});
|
|
84
|
+
stderrWriteSpy = vi.spyOn(process.stderr, 'write').mockImplementation((chunk) => {
|
|
85
|
+
stderrOutput += String(chunk);
|
|
86
|
+
return true;
|
|
87
|
+
});
|
|
88
|
+
setOutputMode('auto');
|
|
89
|
+
vi.clearAllMocks();
|
|
90
|
+
});
|
|
91
|
+
afterEach(() => {
|
|
92
|
+
stdoutWriteSpy.mockRestore();
|
|
93
|
+
stderrWriteSpy.mockRestore();
|
|
94
|
+
setOutputMode('auto');
|
|
95
|
+
});
|
|
96
|
+
describe('runConstellation — JSON mode (non-TTY)', () => {
|
|
97
|
+
it('calls chain.getConstellation with the correct entryId', withTty(false, async () => {
|
|
98
|
+
mcpCallMock.mockResolvedValue(CONSTELLATION_FIXTURE);
|
|
99
|
+
await runConstellation({ entryId: 'BET-181' });
|
|
100
|
+
expect(mcpCallMock).toHaveBeenCalledWith('chain.getConstellation', { entryId: 'BET-181' });
|
|
101
|
+
}));
|
|
102
|
+
it('outputs entry and grouped relations as JSON in non-TTY mode', withTty(false, async () => {
|
|
103
|
+
mcpCallMock.mockResolvedValue(CONSTELLATION_FIXTURE);
|
|
104
|
+
await runConstellation({ entryId: 'BET-181' });
|
|
105
|
+
const parsed = JSON.parse(stdoutOutput);
|
|
106
|
+
expect(parsed.entry.entryId).toBe('BET-181');
|
|
107
|
+
expect(parsed.entry.name).toBe('CLI Agent-Native Foundation');
|
|
108
|
+
expect(parsed.relations).toHaveProperty('part_of');
|
|
109
|
+
expect(parsed.relations).toHaveProperty('informed_by');
|
|
110
|
+
expect(parsed.summary.totalRelations).toBe(3);
|
|
111
|
+
}));
|
|
112
|
+
it('strips Convex internals in JSON mode', withTty(false, async () => {
|
|
113
|
+
const fixtureWithInternals = {
|
|
114
|
+
...CONSTELLATION_FIXTURE,
|
|
115
|
+
entry: { ...CONSTELLATION_FIXTURE.entry, _id: 'sys-id', _creationTime: 999999 },
|
|
116
|
+
};
|
|
117
|
+
mcpCallMock.mockResolvedValue(fixtureWithInternals);
|
|
118
|
+
await runConstellation({ entryId: 'BET-181' });
|
|
119
|
+
const parsed = JSON.parse(stdoutOutput);
|
|
120
|
+
expect(parsed.entry).not.toHaveProperty('_id');
|
|
121
|
+
expect(parsed.entry).not.toHaveProperty('_creationTime');
|
|
122
|
+
}));
|
|
123
|
+
});
|
|
124
|
+
describe('runConstellation — pretty mode (TTY)', () => {
|
|
125
|
+
it('outputs human-readable grouped view in TTY mode', withTty(true, async () => {
|
|
126
|
+
mcpCallMock.mockResolvedValue(CONSTELLATION_FIXTURE);
|
|
127
|
+
await runConstellation({ entryId: 'BET-181' });
|
|
128
|
+
expect(stdoutOutput).toContain('BET-181');
|
|
129
|
+
expect(stdoutOutput).toContain('CLI Agent-Native Foundation');
|
|
130
|
+
}));
|
|
131
|
+
it('shows relation types grouped in TTY output', withTty(true, async () => {
|
|
132
|
+
mcpCallMock.mockResolvedValue(CONSTELLATION_FIXTURE);
|
|
133
|
+
await runConstellation({ entryId: 'BET-181' });
|
|
134
|
+
expect(stdoutOutput).toContain('part_of');
|
|
135
|
+
expect(stdoutOutput).toContain('informed_by');
|
|
136
|
+
expect(stdoutOutput).toContain('DEC-299');
|
|
137
|
+
expect(stdoutOutput).toContain('FEAT-100');
|
|
138
|
+
}));
|
|
139
|
+
it('shows direction arrows in TTY output', withTty(true, async () => {
|
|
140
|
+
mcpCallMock.mockResolvedValue(CONSTELLATION_FIXTURE);
|
|
141
|
+
await runConstellation({ entryId: 'BET-181' });
|
|
142
|
+
// outgoing → for part_of, incoming ← for informed_by
|
|
143
|
+
expect(stdoutOutput).toContain('→');
|
|
144
|
+
expect(stdoutOutput).toContain('←');
|
|
145
|
+
}));
|
|
146
|
+
});
|
|
147
|
+
describe('runConstellation — edge case: entry with no relations', () => {
|
|
148
|
+
it('returns entry-only output with empty relations object', withTty(false, async () => {
|
|
149
|
+
const noRelationsFixture = {
|
|
150
|
+
entry: {
|
|
151
|
+
entryId: 'BET-999',
|
|
152
|
+
name: 'Orphaned Bet',
|
|
153
|
+
collectionSlug: 'bets',
|
|
154
|
+
collectionName: 'Bets',
|
|
155
|
+
status: 'draft',
|
|
156
|
+
},
|
|
157
|
+
relations: {},
|
|
158
|
+
summary: {
|
|
159
|
+
totalRelations: 0,
|
|
160
|
+
relationTypes: [],
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
mcpCallMock.mockResolvedValue(noRelationsFixture);
|
|
164
|
+
await runConstellation({ entryId: 'BET-999' });
|
|
165
|
+
const parsed = JSON.parse(stdoutOutput);
|
|
166
|
+
expect(parsed.entry.entryId).toBe('BET-999');
|
|
167
|
+
expect(parsed.relations).toEqual({});
|
|
168
|
+
expect(parsed.summary.totalRelations).toBe(0);
|
|
169
|
+
expect(parsed.summary.relationTypes).toHaveLength(0);
|
|
170
|
+
}));
|
|
171
|
+
it('shows "No relations" in TTY mode for entry with no relations', withTty(true, async () => {
|
|
172
|
+
const noRelationsFixture = {
|
|
173
|
+
entry: {
|
|
174
|
+
entryId: 'BET-999',
|
|
175
|
+
name: 'Orphaned Bet',
|
|
176
|
+
collectionSlug: 'bets',
|
|
177
|
+
collectionName: 'Bets',
|
|
178
|
+
status: 'draft',
|
|
179
|
+
},
|
|
180
|
+
relations: {},
|
|
181
|
+
summary: {
|
|
182
|
+
totalRelations: 0,
|
|
183
|
+
relationTypes: [],
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
mcpCallMock.mockResolvedValue(noRelationsFixture);
|
|
187
|
+
await runConstellation({ entryId: 'BET-999' });
|
|
188
|
+
expect(stdoutOutput).toContain('No relations');
|
|
189
|
+
}));
|
|
190
|
+
});
|
|
191
|
+
describe('runConstellation — relation types derive from server response', () => {
|
|
192
|
+
it('renders any relation type returned by the server, not a hardcoded list', withTty(false, async () => {
|
|
193
|
+
// Use a novel relation type that doesn't match any hardcoded list
|
|
194
|
+
const customRelationFixture = {
|
|
195
|
+
entry: {
|
|
196
|
+
entryId: 'DEC-999',
|
|
197
|
+
name: 'Custom Decision',
|
|
198
|
+
collectionSlug: 'decisions',
|
|
199
|
+
collectionName: 'Decisions',
|
|
200
|
+
status: 'active',
|
|
201
|
+
},
|
|
202
|
+
relations: {
|
|
203
|
+
related_to: [
|
|
204
|
+
{
|
|
205
|
+
entryId: 'TEN-42',
|
|
206
|
+
name: 'Some Tension',
|
|
207
|
+
collectionSlug: 'tensions',
|
|
208
|
+
collectionName: 'Tensions',
|
|
209
|
+
direction: 'outgoing',
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
governs: [
|
|
213
|
+
{
|
|
214
|
+
entryId: 'FEAT-7',
|
|
215
|
+
name: 'Some Feature',
|
|
216
|
+
collectionSlug: 'features',
|
|
217
|
+
collectionName: 'Features',
|
|
218
|
+
direction: 'outgoing',
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
blocks: [
|
|
222
|
+
{
|
|
223
|
+
entryId: 'BET-55',
|
|
224
|
+
name: 'Blocked Bet',
|
|
225
|
+
collectionSlug: 'bets',
|
|
226
|
+
collectionName: 'Bets',
|
|
227
|
+
direction: 'outgoing',
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
summary: {
|
|
232
|
+
totalRelations: 3,
|
|
233
|
+
relationTypes: ['related_to', 'governs', 'blocks'],
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
mcpCallMock.mockResolvedValue(customRelationFixture);
|
|
237
|
+
await runConstellation({ entryId: 'DEC-999' });
|
|
238
|
+
const parsed = JSON.parse(stdoutOutput);
|
|
239
|
+
// Verify the CLI passes through whatever the server returns
|
|
240
|
+
expect(parsed.relations).toHaveProperty('related_to');
|
|
241
|
+
expect(parsed.relations).toHaveProperty('governs');
|
|
242
|
+
expect(parsed.relations).toHaveProperty('blocks');
|
|
243
|
+
expect(parsed.summary.relationTypes).toContain('related_to');
|
|
244
|
+
expect(parsed.summary.relationTypes).toContain('governs');
|
|
245
|
+
expect(parsed.summary.relationTypes).toContain('blocks');
|
|
246
|
+
}));
|
|
247
|
+
});
|
|
248
|
+
describe('runConstellation — error handling', () => {
|
|
249
|
+
it('exits 1 with error message when entry is not found', withTty(false, async () => {
|
|
250
|
+
mcpCallMock.mockRejectedValue(new Error('Entry "NOTEXIST-9999" not found.'));
|
|
251
|
+
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => { throw new Error('process.exit'); });
|
|
252
|
+
await expect(runConstellation({ entryId: 'NOTEXIST-9999' })).rejects.toThrow('process.exit');
|
|
253
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
254
|
+
const errParsed = JSON.parse(stderrOutput);
|
|
255
|
+
expect(errParsed).toHaveProperty('error');
|
|
256
|
+
expect(errParsed.error).toContain('NOTEXIST-9999');
|
|
257
|
+
exitSpy.mockRestore();
|
|
258
|
+
}));
|
|
259
|
+
});
|
|
260
|
+
//# sourceMappingURL=constellation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constellation.test.js","sourceRoot":"","sources":["../../src/__tests__/constellation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fields.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/fields.test.ts"],"names":[],"mappings":""}
|