@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.
Files changed (166) hide show
  1. package/README.md +84 -1
  2. package/dist/__tests__/capture.test.d.ts +2 -0
  3. package/dist/__tests__/capture.test.d.ts.map +1 -0
  4. package/dist/__tests__/capture.test.js +86 -0
  5. package/dist/__tests__/capture.test.js.map +1 -0
  6. package/dist/__tests__/constellation.test.d.ts +2 -0
  7. package/dist/__tests__/constellation.test.d.ts.map +1 -0
  8. package/dist/__tests__/constellation.test.js +260 -0
  9. package/dist/__tests__/constellation.test.js.map +1 -0
  10. package/dist/__tests__/fields.test.d.ts +2 -0
  11. package/dist/__tests__/fields.test.d.ts.map +1 -0
  12. package/dist/__tests__/fields.test.js +238 -0
  13. package/dist/__tests__/fields.test.js.map +1 -0
  14. package/dist/__tests__/handshake.test.d.ts +2 -0
  15. package/dist/__tests__/handshake.test.d.ts.map +1 -0
  16. package/dist/__tests__/handshake.test.js +187 -0
  17. package/dist/__tests__/handshake.test.js.map +1 -0
  18. package/dist/__tests__/relate.test.d.ts +2 -0
  19. package/dist/__tests__/relate.test.d.ts.map +1 -0
  20. package/dist/__tests__/relate.test.js +79 -0
  21. package/dist/__tests__/relate.test.js.map +1 -0
  22. package/dist/__tests__/repo-detect.test.d.ts +2 -0
  23. package/dist/__tests__/repo-detect.test.d.ts.map +1 -0
  24. package/dist/__tests__/repo-detect.test.js +119 -0
  25. package/dist/__tests__/repo-detect.test.js.map +1 -0
  26. package/dist/__tests__/runner.test.d.ts +2 -0
  27. package/dist/__tests__/runner.test.d.ts.map +1 -0
  28. package/dist/__tests__/runner.test.js +215 -0
  29. package/dist/__tests__/runner.test.js.map +1 -0
  30. package/dist/__tests__/session-touch.test.d.ts +2 -0
  31. package/dist/__tests__/session-touch.test.d.ts.map +1 -0
  32. package/dist/__tests__/session-touch.test.js +134 -0
  33. package/dist/__tests__/session-touch.test.js.map +1 -0
  34. package/dist/__tests__/session.test.d.ts +2 -0
  35. package/dist/__tests__/session.test.d.ts.map +1 -0
  36. package/dist/__tests__/session.test.js +52 -0
  37. package/dist/__tests__/session.test.js.map +1 -0
  38. package/dist/__tests__/strip.test.d.ts +2 -0
  39. package/dist/__tests__/strip.test.d.ts.map +1 -0
  40. package/dist/__tests__/strip.test.js +136 -0
  41. package/dist/__tests__/strip.test.js.map +1 -0
  42. package/dist/__tests__/update.test.d.ts +2 -0
  43. package/dist/__tests__/update.test.d.ts.map +1 -0
  44. package/dist/__tests__/update.test.js +148 -0
  45. package/dist/__tests__/update.test.js.map +1 -0
  46. package/dist/commands/capture.d.ts +21 -0
  47. package/dist/commands/capture.d.ts.map +1 -0
  48. package/dist/commands/capture.js +100 -0
  49. package/dist/commands/capture.js.map +1 -0
  50. package/dist/commands/constellation.d.ts +11 -0
  51. package/dist/commands/constellation.d.ts.map +1 -0
  52. package/dist/commands/constellation.js +28 -0
  53. package/dist/commands/constellation.js.map +1 -0
  54. package/dist/commands/context.d.ts +2 -1
  55. package/dist/commands/context.d.ts.map +1 -1
  56. package/dist/commands/context.js +15 -9
  57. package/dist/commands/context.js.map +1 -1
  58. package/dist/commands/fields.d.ts +9 -0
  59. package/dist/commands/fields.d.ts.map +1 -0
  60. package/dist/commands/fields.js +26 -0
  61. package/dist/commands/fields.js.map +1 -0
  62. package/dist/commands/get.d.ts +8 -1
  63. package/dist/commands/get.d.ts.map +1 -1
  64. package/dist/commands/get.js +51 -6
  65. package/dist/commands/get.js.map +1 -1
  66. package/dist/commands/handshake.d.ts +18 -0
  67. package/dist/commands/handshake.d.ts.map +1 -0
  68. package/dist/commands/handshake.js +378 -0
  69. package/dist/commands/handshake.js.map +1 -0
  70. package/dist/commands/ingest.d.ts +1 -0
  71. package/dist/commands/ingest.d.ts.map +1 -1
  72. package/dist/commands/ingest.js +25 -8
  73. package/dist/commands/ingest.js.map +1 -1
  74. package/dist/commands/orient.d.ts +1 -0
  75. package/dist/commands/orient.d.ts.map +1 -1
  76. package/dist/commands/orient.js +13 -8
  77. package/dist/commands/orient.js.map +1 -1
  78. package/dist/commands/relate.d.ts +15 -0
  79. package/dist/commands/relate.d.ts.map +1 -0
  80. package/dist/commands/relate.js +72 -0
  81. package/dist/commands/relate.js.map +1 -0
  82. package/dist/commands/search.d.ts +1 -0
  83. package/dist/commands/search.d.ts.map +1 -1
  84. package/dist/commands/search.js +5 -3
  85. package/dist/commands/search.js.map +1 -1
  86. package/dist/commands/session.d.ts +20 -0
  87. package/dist/commands/session.d.ts.map +1 -0
  88. package/dist/commands/session.js +134 -0
  89. package/dist/commands/session.js.map +1 -0
  90. package/dist/commands/update.d.ts +16 -0
  91. package/dist/commands/update.d.ts.map +1 -0
  92. package/dist/commands/update.js +89 -0
  93. package/dist/commands/update.js.map +1 -0
  94. package/dist/formatters/capture.d.ts +30 -0
  95. package/dist/formatters/capture.d.ts.map +1 -0
  96. package/dist/formatters/capture.js +58 -0
  97. package/dist/formatters/capture.js.map +1 -0
  98. package/dist/formatters/constellation.d.ts +34 -0
  99. package/dist/formatters/constellation.d.ts.map +1 -0
  100. package/dist/formatters/constellation.js +38 -0
  101. package/dist/formatters/constellation.js.map +1 -0
  102. package/dist/formatters/fields.d.ts +32 -0
  103. package/dist/formatters/fields.d.ts.map +1 -0
  104. package/dist/formatters/fields.js +49 -0
  105. package/dist/formatters/fields.js.map +1 -0
  106. package/dist/formatters/handshake.d.ts +17 -0
  107. package/dist/formatters/handshake.d.ts.map +1 -0
  108. package/dist/formatters/handshake.js +51 -0
  109. package/dist/formatters/handshake.js.map +1 -0
  110. package/dist/formatters/relate.d.ts +11 -0
  111. package/dist/formatters/relate.d.ts.map +1 -0
  112. package/dist/formatters/relate.js +10 -0
  113. package/dist/formatters/relate.js.map +1 -0
  114. package/dist/formatters/session.d.ts +11 -0
  115. package/dist/formatters/session.d.ts.map +1 -0
  116. package/dist/formatters/session.js +51 -0
  117. package/dist/formatters/session.js.map +1 -0
  118. package/dist/formatters/update.d.ts +17 -0
  119. package/dist/formatters/update.d.ts.map +1 -0
  120. package/dist/formatters/update.js +43 -0
  121. package/dist/formatters/update.js.map +1 -0
  122. package/dist/generators/adapters.d.ts +10 -0
  123. package/dist/generators/adapters.d.ts.map +1 -0
  124. package/dist/generators/adapters.js +102 -0
  125. package/dist/generators/adapters.js.map +1 -0
  126. package/dist/generators/briefing-md.d.ts +8 -0
  127. package/dist/generators/briefing-md.d.ts.map +1 -0
  128. package/dist/generators/briefing-md.js +51 -0
  129. package/dist/generators/briefing-md.js.map +1 -0
  130. package/dist/generators/context-md.d.ts +8 -0
  131. package/dist/generators/context-md.d.ts.map +1 -0
  132. package/dist/generators/context-md.js +123 -0
  133. package/dist/generators/context-md.js.map +1 -0
  134. package/dist/generators/portable-knowledge.d.ts +72 -0
  135. package/dist/generators/portable-knowledge.d.ts.map +1 -0
  136. package/dist/generators/portable-knowledge.js +246 -0
  137. package/dist/generators/portable-knowledge.js.map +1 -0
  138. package/dist/generators/portable-knowledge.test.d.ts +2 -0
  139. package/dist/generators/portable-knowledge.test.d.ts.map +1 -0
  140. package/dist/generators/portable-knowledge.test.js +399 -0
  141. package/dist/generators/portable-knowledge.test.js.map +1 -0
  142. package/dist/index.d.ts +3 -2
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +231 -6
  145. package/dist/index.js.map +1 -1
  146. package/dist/lib/client.d.ts +19 -0
  147. package/dist/lib/client.d.ts.map +1 -1
  148. package/dist/lib/client.js +102 -8
  149. package/dist/lib/client.js.map +1 -1
  150. package/dist/lib/repo-detect.d.ts +14 -0
  151. package/dist/lib/repo-detect.d.ts.map +1 -0
  152. package/dist/lib/repo-detect.js +58 -0
  153. package/dist/lib/repo-detect.js.map +1 -0
  154. package/dist/lib/runner.d.ts +31 -0
  155. package/dist/lib/runner.d.ts.map +1 -0
  156. package/dist/lib/runner.js +65 -0
  157. package/dist/lib/runner.js.map +1 -0
  158. package/dist/lib/session.d.ts +17 -0
  159. package/dist/lib/session.d.ts.map +1 -0
  160. package/dist/lib/session.js +43 -0
  161. package/dist/lib/session.js.map +1 -0
  162. package/dist/lib/strip.d.ts +11 -0
  163. package/dist/lib/strip.d.ts.map +1 -0
  164. package/dist/lib/strip.js +26 -0
  165. package/dist/lib/strip.js.map +1 -0
  166. package/package.json +6 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Product Brain CLI (`pb`)
2
2
 
3
- Read-only CLI for Chain knowledge: orient, search, get entry, gather context. Uses your Product Brain API key (same as MCP).
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=capture.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=constellation.test.d.ts.map
@@ -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":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAE5B,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;CACtD,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,GAAY,EAAE,EAAE,CACvC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAC/E;CACF,CAAC,CAAC,CAAC;AAEJ,4CAA4C;AAC5C,MAAM,qBAAqB,GAAG;IAC5B,KAAK,EAAE;QACL,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,6BAA6B;QACnC,cAAc,EAAE,MAAM;QACtB,cAAc,EAAE,MAAM;QACtB,MAAM,EAAE,QAAQ;KACjB;IACD,SAAS,EAAE;QACT,OAAO,EAAE;YACP;gBACE,OAAO,EAAE,UAAU;gBACnB,IAAI,EAAE,mBAAmB;gBACzB,cAAc,EAAE,UAAU;gBAC1B,cAAc,EAAE,UAAU;gBAC1B,SAAS,EAAE,UAAmB;aAC/B;SACF;QACD,WAAW,EAAE;YACX;gBACE,OAAO,EAAE,SAAS;gBAClB,IAAI,EAAE,sCAAsC;gBAC5C,cAAc,EAAE,WAAW;gBAC3B,cAAc,EAAE,WAAW;gBAC3B,SAAS,EAAE,UAAmB;aAC/B;YACD;gBACE,OAAO,EAAE,QAAQ;gBACjB,IAAI,EAAE,gCAAgC;gBACtC,cAAc,EAAE,WAAW;gBAC3B,cAAc,EAAE,WAAW;gBAC3B,SAAS,EAAE,UAAmB;aAC/B;SACF;KACF;IACD,OAAO,EAAE;QACP,cAAc,EAAE,CAAC;QACjB,aAAa,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;KAC1C;CACF,CAAC;AAEF,IAAI,YAAoB,CAAC;AACzB,IAAI,YAAoB,CAAC;AACzB,IAAI,cAA2C,CAAC;AAChD,IAAI,cAA2C,CAAC;AAEhD,SAAS,OAAO,CAAC,KAAc,EAAE,EAA8B;IAC7D,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QACtC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACrG,IAAI,CAAC;YACH,MAAM,EAAE,EAAE,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1G,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,UAAU,CAAC,GAAG,EAAE;IACd,YAAY,GAAG,EAAE,CAAC;IAClB,YAAY,GAAG,EAAE,CAAC;IAClB,cAAc,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9E,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,cAAc,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9E,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,EAAE,CAAC,aAAa,EAAE,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,cAAc,CAAC,WAAW,EAAE,CAAC;IAC7B,cAAc,CAAC,WAAW,EAAE,CAAC;IAC7B,aAAa,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,uDAAuD,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACpF,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC,CAAC;IAEJ,EAAE,CAAC,6DAA6D,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QAC1F,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC,CAAC;IAEJ,EAAE,CAAC,sCAAsC,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,oBAAoB,GAAG;YAC3B,GAAG,qBAAqB;YACxB,KAAK,EAAE,EAAE,GAAG,qBAAqB,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE;SAChF,CAAC;QACF,WAAW,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAAC;QACpD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,iDAAiD,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAC7E,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC,CAAC;IAEJ,EAAE,CAAC,4CAA4C,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QACxE,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC,CAAC;IAEJ,EAAE,CAAC,sCAAsC,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAClE,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,qDAAqD;QACrD,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACrE,EAAE,CAAC,uDAAuD,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,kBAAkB,GAAG;YACzB,KAAK,EAAE;gBACL,OAAO,EAAE,SAAS;gBAClB,IAAI,EAAE,cAAc;gBACpB,cAAc,EAAE,MAAM;gBACtB,cAAc,EAAE,MAAM;gBACtB,MAAM,EAAE,OAAO;aAChB;YACD,SAAS,EAAE,EAAE;YACb,OAAO,EAAE;gBACP,cAAc,EAAE,CAAC;gBACjB,aAAa,EAAE,EAAE;aAClB;SACF,CAAC;QACF,WAAW,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;QAClD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC,CAAC;IAEJ,EAAE,CAAC,8DAA8D,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,kBAAkB,GAAG;YACzB,KAAK,EAAE;gBACL,OAAO,EAAE,SAAS;gBAClB,IAAI,EAAE,cAAc;gBACpB,cAAc,EAAE,MAAM;gBACtB,cAAc,EAAE,MAAM;gBACtB,MAAM,EAAE,OAAO;aAChB;YACD,SAAS,EAAE,EAAE;YACb,OAAO,EAAE;gBACP,cAAc,EAAE,CAAC;gBACjB,aAAa,EAAE,EAAE;aAClB;SACF,CAAC;QACF,WAAW,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;QAClD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+DAA+D,EAAE,GAAG,EAAE;IAC7E,EAAE,CAAC,wEAAwE,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACrG,kEAAkE;QAClE,MAAM,qBAAqB,GAAG;YAC5B,KAAK,EAAE;gBACL,OAAO,EAAE,SAAS;gBAClB,IAAI,EAAE,iBAAiB;gBACvB,cAAc,EAAE,WAAW;gBAC3B,cAAc,EAAE,WAAW;gBAC3B,MAAM,EAAE,QAAQ;aACjB;YACD,SAAS,EAAE;gBACT,UAAU,EAAE;oBACV;wBACE,OAAO,EAAE,QAAQ;wBACjB,IAAI,EAAE,cAAc;wBACpB,cAAc,EAAE,UAAU;wBAC1B,cAAc,EAAE,UAAU;wBAC1B,SAAS,EAAE,UAAmB;qBAC/B;iBACF;gBACD,OAAO,EAAE;oBACP;wBACE,OAAO,EAAE,QAAQ;wBACjB,IAAI,EAAE,cAAc;wBACpB,cAAc,EAAE,UAAU;wBAC1B,cAAc,EAAE,UAAU;wBAC1B,SAAS,EAAE,UAAmB;qBAC/B;iBACF;gBACD,MAAM,EAAE;oBACN;wBACE,OAAO,EAAE,QAAQ;wBACjB,IAAI,EAAE,aAAa;wBACnB,cAAc,EAAE,MAAM;wBACtB,cAAc,EAAE,MAAM;wBACtB,SAAS,EAAE,UAAmB;qBAC/B;iBACF;aACF;YACD,OAAO,EAAE;gBACP,cAAc,EAAE,CAAC;gBACjB,aAAa,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC;aACnD;SACF,CAAC;QACF,WAAW,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC;QACrD,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxC,4DAA4D;QAC5D,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,oDAAoD,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;QACjF,WAAW,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC7E,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzG,MAAM,MAAM,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAE7F,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAEnD,OAAO,CAAC,WAAW,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC,CAAC;AACN,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fields.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/fields.test.ts"],"names":[],"mappings":""}