@principal-ai/principal-view-react 0.16.55 → 0.16.57

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 (125) hide show
  1. package/dist/graphify/consolidated.d.ts +16 -1
  2. package/dist/graphify/consolidated.d.ts.map +1 -1
  3. package/dist/graphify/index.d.ts +1 -1
  4. package/dist/graphify/index.d.ts.map +1 -1
  5. package/dist/graphify/index.js.map +1 -1
  6. package/dist/graphify/kind.d.ts +1 -1
  7. package/dist/graphify/kind.d.ts.map +1 -1
  8. package/dist/graphify/kind.js +7 -1
  9. package/dist/graphify/kind.js.map +1 -1
  10. package/dist/index.d.ts +5 -4
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -2
  13. package/dist/index.js.map +1 -1
  14. package/dist/pierre/constructColors.d.ts +24 -0
  15. package/dist/pierre/constructColors.d.ts.map +1 -0
  16. package/dist/pierre/constructColors.js +91 -0
  17. package/dist/pierre/constructColors.js.map +1 -0
  18. package/dist/pierre/index.d.ts +2 -0
  19. package/dist/pierre/index.d.ts.map +1 -1
  20. package/dist/pierre/index.js +1 -0
  21. package/dist/pierre/index.js.map +1 -1
  22. package/dist/pierre/pierreSyntaxTheme.d.ts +11 -0
  23. package/dist/pierre/pierreSyntaxTheme.d.ts.map +1 -0
  24. package/dist/pierre/pierreSyntaxTheme.js +20 -0
  25. package/dist/pierre/pierreSyntaxTheme.js.map +1 -0
  26. package/dist/pierre/syntaxTokens.d.ts +11 -0
  27. package/dist/pierre/syntaxTokens.d.ts.map +1 -0
  28. package/dist/pierre/syntaxTokens.js +51 -0
  29. package/dist/pierre/syntaxTokens.js.map +1 -0
  30. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts +8 -0
  31. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts.map +1 -0
  32. package/dist/stories/Subsystem/ComponentGraph/fixtures.js +116 -0
  33. package/dist/stories/Subsystem/ComponentGraph/fixtures.js.map +1 -0
  34. package/dist/subsystem/ComponentDeclaration.d.ts +2 -2
  35. package/dist/subsystem/ComponentDeclaration.d.ts.map +1 -1
  36. package/dist/subsystem/ComponentDeclaration.js +47 -24
  37. package/dist/subsystem/ComponentDeclaration.js.map +1 -1
  38. package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
  39. package/dist/subsystem/SubsystemComponentGraph.js +23 -2
  40. package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
  41. package/dist/subsystem/formatDeclaration.d.ts.map +1 -1
  42. package/dist/subsystem/formatDeclaration.js +49 -10
  43. package/dist/subsystem/formatDeclaration.js.map +1 -1
  44. package/dist/subsystem/model.d.ts +57 -12
  45. package/dist/subsystem/model.d.ts.map +1 -1
  46. package/dist/subsystem/model.js +54 -24
  47. package/dist/subsystem/model.js.map +1 -1
  48. package/dist/subsystem/nodes.d.ts +4 -1
  49. package/dist/subsystem/nodes.d.ts.map +1 -1
  50. package/dist/subsystem/nodes.js +70 -21
  51. package/dist/subsystem/nodes.js.map +1 -1
  52. package/dist/subsystem/tokenizeComponent.d.ts +4 -3
  53. package/dist/subsystem/tokenizeComponent.d.ts.map +1 -1
  54. package/dist/subsystem/tokenizeComponent.js +7 -12
  55. package/dist/subsystem/tokenizeComponent.js.map +1 -1
  56. package/dist/subsystem/tokenizeFormatted.d.ts +3 -6
  57. package/dist/subsystem/tokenizeFormatted.d.ts.map +1 -1
  58. package/dist/subsystem/tokenizeFormatted.js +4 -75
  59. package/dist/subsystem/tokenizeFormatted.js.map +1 -1
  60. package/package.json +3 -1
  61. package/src/graphify/consolidated.ts +18 -1
  62. package/src/graphify/index.ts +1 -0
  63. package/src/graphify/kind.ts +7 -1
  64. package/src/index.ts +5 -3
  65. package/src/pierre/constructColors.test.ts +52 -0
  66. package/src/pierre/constructColors.ts +112 -0
  67. package/src/pierre/index.ts +5 -0
  68. package/src/pierre/pierreSyntaxTheme.ts +23 -0
  69. package/src/pierre/syntaxTokens.test.ts +35 -0
  70. package/src/pierre/syntaxTokens.ts +60 -0
  71. package/src/stories/{BoundaryNodes.stories.tsx → Audit/BoundaryNodes.stories.tsx} +1 -1
  72. package/src/stories/{CanvasEdgeTypes.stories.tsx → Audit/CanvasEdgeTypes.stories.tsx} +1 -1
  73. package/src/stories/{CanvasNodeTypes.stories.tsx → Audit/CanvasNodeTypes.stories.tsx} +1 -1
  74. package/src/stories/{ColorPriority.stories.tsx → Audit/ColorPriority.stories.tsx} +1 -1
  75. package/src/stories/{DiamondBadges.stories.tsx → Audit/DiamondBadges.stories.tsx} +1 -1
  76. package/src/stories/{NodeDimensionsTesting.stories.tsx → Audit/NodeDimensionsTesting.stories.tsx} +2 -2
  77. package/src/stories/{NodeFieldsAudit.stories.tsx → Audit/NodeFieldsAudit.stories.tsx} +1 -1
  78. package/src/stories/{NodeFontSizeTesting.stories.tsx → Audit/NodeFontSizeTesting.stories.tsx} +2 -2
  79. package/src/stories/{NodeShapes.stories.tsx → Audit/NodeShapes.stories.tsx} +1 -1
  80. package/src/stories/{WideNodesTesting.stories.tsx → Audit/WideNodesTesting.stories.tsx} +2 -2
  81. package/src/stories/{dashboard → Components}/DashboardRenderer.stories.tsx +2 -2
  82. package/src/stories/{GraphRenderer.stories.tsx → Components/GraphRenderer.stories.tsx} +2 -2
  83. package/src/stories/{MultiCanvasRenderer.stories.tsx → Components/MultiCanvasRenderer.stories.tsx} +2 -2
  84. package/src/stories/{SequenceDiagram.stories.tsx → Components/SequenceDiagram.stories.tsx} +2 -2
  85. package/src/stories/{StateView.stories.tsx → Components/StateView.stories.tsx} +2 -2
  86. package/src/stories/{TraceViewer.stories.tsx → Components/TraceViewer.stories.tsx} +3 -3
  87. package/src/stories/{WorkflowSequenceDiagram.stories.tsx → Components/WorkflowSequenceDiagram.stories.tsx} +1 -1
  88. package/src/stories/{AnimationWorkshop.stories.tsx → Features/AnimationWorkshop.stories.tsx} +5 -5
  89. package/src/stories/{ChangeTypeVisual.stories.tsx → Features/ChangeTypeVisual.stories.tsx} +2 -2
  90. package/src/stories/{EventDrivenAnimations.stories.tsx → Features/EventDrivenAnimations.stories.tsx} +2 -2
  91. package/src/stories/{MultiConfig.stories.tsx → Features/MultiConfig.stories.tsx} +2 -2
  92. package/src/stories/{ElkEdgeRouting.stories.tsx → Layout/ElkEdgeRouting.stories.tsx} +2 -2
  93. package/src/stories/{GraphOrientation.stories.tsx → Layout/GraphOrientation.stories.tsx} +3 -3
  94. package/src/stories/{MultiDirectionalConnections.stories.tsx → Layout/MultiDirectionalConnections.stories.tsx} +2 -2
  95. package/src/stories/{NodeDefinitionComparison.stories.tsx → Nodes/NodeDefinitionComparison.stories.tsx} +2 -2
  96. package/src/stories/{NodeNameFallbacks.stories.tsx → Nodes/NodeNameFallbacks.stories.tsx} +2 -2
  97. package/src/stories/{NumericColors.stories.tsx → Nodes/NumericColors.stories.tsx} +2 -2
  98. package/src/stories/{EventNameDisplay.stories.tsx → OTEL/EventNameDisplay.stories.tsx} +2 -2
  99. package/src/stories/{EventNameFallback.stories.tsx → OTEL/EventNameFallback.stories.tsx} +2 -2
  100. package/src/stories/{OtelComponents.stories.tsx → OTEL/OtelComponents.stories.tsx} +3 -3
  101. package/src/stories/{OtelNodeTypesPrototype.stories.tsx → OTEL/OtelNodeTypesPrototype.stories.tsx} +2 -2
  102. package/src/stories/{RawEventCards.stories.tsx → OTEL/RawEventCards.stories.tsx} +3 -3
  103. package/src/stories/{SpanBadges.stories.tsx → OTEL/SpanBadges.stories.tsx} +1 -1
  104. package/src/stories/{ValidationEventsCanvas.stories.tsx → OTEL/ValidationEventsCanvas.stories.tsx} +3 -3
  105. package/src/stories/{BacklogMdCanvases.stories.tsx → RealWorld/BacklogMdCanvases.stories.tsx} +2 -2
  106. package/src/stories/{FileCitySequence.stories.tsx → RealWorld/FileCitySequence.stories.tsx} +4 -4
  107. package/src/stories/{RealCanvasFiles.stories.tsx → RealWorld/RealCanvasFiles.stories.tsx} +7 -7
  108. package/src/stories/{ComponentDeclarationAudit.stories.tsx → Subsystem/ComponentDeclarationAudit.stories.tsx} +19 -20
  109. package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +365 -0
  110. package/src/stories/Subsystem/ComponentGraph/Basics.stories.tsx +137 -0
  111. package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +238 -0
  112. package/src/stories/Subsystem/ComponentGraph/DetailPanel.stories.tsx +315 -0
  113. package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +959 -0
  114. package/src/stories/Subsystem/ComponentGraph/Spotlights.stories.tsx +646 -0
  115. package/src/stories/Subsystem/ComponentGraph/fixtures.ts +129 -0
  116. package/src/subsystem/ComponentDeclaration.tsx +64 -26
  117. package/src/subsystem/SubsystemComponentGraph.tsx +26 -6
  118. package/src/subsystem/formatDeclaration.ts +57 -11
  119. package/src/subsystem/model.test.ts +38 -6
  120. package/src/subsystem/model.ts +110 -31
  121. package/src/subsystem/nodes.tsx +103 -27
  122. package/src/subsystem/tokenizeComponent.ts +12 -12
  123. package/src/subsystem/tokenizeFormatted.ts +9 -82
  124. package/src/stories/SubsystemComponentGraph.stories.tsx +0 -1225
  125. /package/src/stories/{dashboard/sample-dashboards → data}/activity-feed-analytics.dashboard.json +0 -0
@@ -1,1225 +0,0 @@
1
- import React, { useState } from 'react';
2
- import '@xyflow/react/dist/style.css';
3
- import type { Meta, StoryObj } from '@storybook/react';
4
- import { ThemeProvider, defaultTheme, defaultEditorTheme } from '@principal-ade/industry-theme';
5
- import { SubsystemComponentGraph } from '../subsystem/SubsystemComponentGraph';
6
- import { PierreFileView, PierreSnippetView } from '../pierre';
7
- import type { SubsystemComponent, SubsystemComponentEdge } from '../subsystem/model';
8
- import type { SubsystemOpenFileOptions } from '../subsystem/declarationRef';
9
- import type { GraphifyComponentDetail } from '../graphify';
10
- import componentDeclarationSource from '../subsystem/ComponentDeclaration.tsx?raw';
11
- import resolveSource from '../graphify/resolve.ts?raw';
12
- const meta = {
13
- title: 'Subsystem/Component Graph',
14
- component: SubsystemComponentGraph,
15
- parameters: {
16
- layout: 'fullscreen',
17
- },
18
- tags: ['autodocs'],
19
- decorators: [
20
- (Story) => (
21
- <ThemeProvider theme={defaultEditorTheme}>
22
- <Story />
23
- </ThemeProvider>
24
- ),
25
- ],
26
- } satisfies Meta<typeof SubsystemComponentGraph>;
27
-
28
- export default meta;
29
- type Story = StoryObj<typeof meta>;
30
-
31
- // ---------------------------------------------------------------------------
32
- // Build a subsystem graph from a compact spec - helpers
33
- // ---------------------------------------------------------------------------
34
- function components(
35
- spec: Array<[id: string, name: string, kind: SubsystemComponent['kind'], file: string, purl: string, purpose?: string, symbol?: string, detail?: GraphifyComponentDetail]>,
36
- ): SubsystemComponent[] {
37
- return spec.map(([id, name, kind, file, purl, purpose, symbol, detail]) => ({
38
- id,
39
- name,
40
- kind,
41
- file,
42
- purl,
43
- purpose,
44
- symbol,
45
- detail,
46
- }));
47
- }
48
-
49
- function edges(
50
- spec: Array<[from: string, to: string, mechanism: SubsystemComponentEdge['mechanism'], refs?: string[]]>,
51
- ): SubsystemComponentEdge[] {
52
- return spec.map(([from, to, mechanism, refs], i) => ({
53
- id: `e${i}`,
54
- from,
55
- to,
56
- mechanism,
57
- refs,
58
- }));
59
- }
60
-
61
- // ---------------------------------------------------------------------------
62
- // Minimal: two nodes, one edge — the simplest possible label layout test.
63
- // ---------------------------------------------------------------------------
64
- const twoNodeComponents = components([
65
- ['src', 'TranscriptParser', 'class', 'transcript.ts', 'pkg:github/principal-ai/agent-monitoring', 'parses session records'],
66
- ['dst', 'SessionReader', 'class', 'SessionReader.ts', 'pkg:github/principal-ai/agent-monitoring', 'normalizes sessions into events'],
67
- ]);
68
-
69
- const twoNodeEdges = edges([
70
- ['src', 'dst', 'imports'],
71
- ]);
72
-
73
- function TwoNodeDemo({ showEdgeLabels = true }: { showEdgeLabels?: boolean }) {
74
- const [selected, setSelected] = useState<string | null>(null);
75
- const [selectedEdge, setSelectedEdge] = useState<SubsystemComponentEdge | null>(null);
76
- return (
77
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
78
- <SubsystemComponentGraph
79
- components={twoNodeComponents}
80
- edges={twoNodeEdges}
81
- onSelect={(id) => setSelected(id)}
82
- onEdgeSelect={(e) => setSelectedEdge(e)}
83
- showEdgeLabels={showEdgeLabels}
84
- />
85
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
86
- {selectedEdge
87
- ? `edge: ${selectedEdge.from} --${selectedEdge.mechanism}--> ${selectedEdge.to}`
88
- : selected
89
- ? `selected: ${selected}`
90
- : 'click a component or edge to select it'}
91
- </div>
92
- </div>
93
- );
94
- }
95
-
96
- export const TwoNodeSingleEdge: Story = {
97
- render: () => <TwoNodeDemo />,
98
- };
99
-
100
- export const TwoNodeNoLabels: Story = {
101
- render: () => <TwoNodeDemo showEdgeLabels={false} />,
102
- };
103
-
104
- // ---------------------------------------------------------------------------
105
- // Playground: control the number of nodes in left and right layers.
106
- // All left nodes connect to all right nodes (fan-in / fan-out).
107
- // ---------------------------------------------------------------------------
108
- function PlaygroundDemo({ leftCount, rightCount, showEdgeLabels }: { leftCount: number; rightCount: number; showEdgeLabels: boolean }) {
109
- const comps: SubsystemComponent[] = [];
110
- const edgeList: SubsystemComponentEdge[] = [];
111
-
112
- for (let i = 0; i < leftCount; i++) {
113
- comps.push({
114
- id: `l${i}`,
115
- name: `Left${i}`,
116
- kind: 'class',
117
- file: `left${i}.ts`,
118
- purl: 'pkg:github/principal-ai/playground',
119
- purpose: `left layer node ${i}`,
120
- });
121
- }
122
- for (let i = 0; i < rightCount; i++) {
123
- comps.push({
124
- id: `r${i}`,
125
- name: `Right${i}`,
126
- kind: 'class',
127
- file: `right${i}.ts`,
128
- purl: 'pkg:github/principal-ai/playground',
129
- purpose: `right layer node ${i}`,
130
- });
131
- }
132
-
133
- let ei = 0;
134
- for (let i = 0; i < leftCount; i++) {
135
- for (let j = 0; j < rightCount; j++) {
136
- edgeList.push({ id: `e${ei++}`, from: `l${i}`, to: `r${j}`, mechanism: 'imports' });
137
- }
138
- }
139
-
140
- return (
141
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
142
- <SubsystemComponentGraph components={comps} edges={edgeList} showEdgeLabels={showEdgeLabels} />
143
- </div>
144
- );
145
- }
146
-
147
- export const Playground: Story = {
148
- render: (args) => <PlaygroundDemo {...args} />,
149
- args: {
150
- leftCount: 1,
151
- rightCount: 1,
152
- showEdgeLabels: true,
153
- },
154
- argTypes: {
155
- leftCount: { control: { type: 'number', min: 0, max: 6, step: 1 } },
156
- rightCount: { control: { type: 'number', min: 0, max: 6, step: 1 } },
157
- showEdgeLabels: { control: 'boolean' },
158
- },
159
- };
160
-
161
- // ---------------------------------------------------------------------------
162
- // Primary: opencode V2 event reader subsystem (agent-monitoring) + consumers
163
- // ---------------------------------------------------------------------------
164
- const readerDetail: GraphifyComponentDetail = {
165
- kind: 'class',
166
- methods: [
167
- { nodeId: 'm1', name: 'normalize', returnType: 'SessionEvent[]' },
168
- { nodeId: 'm2', name: 'readSession', parameters: [{ type: 'string' }], returnType: 'SessionRecord' },
169
- { nodeId: 'm3', name: 'toUniversalEvents', returnType: 'UniversalEvent[]' },
170
- ],
171
- properties: [{ name: 'sessionId', type: 'string' }],
172
- extends: [],
173
- implements: ['SessionReaderLike'],
174
- instantiations: [{ nodeId: 'caller1', name: 'capture-session' }],
175
- references: [{ nodeId: 'ref1', name: 'supported-agents', context: 'type' }],
176
- };
177
-
178
- const v2ReaderComponents = components([
179
- ['capture', 'capture script', 'function', 'scripts/capture-session.ts', 'pkg:github/principal-ai/agent-monitoring', 'captures a real session for fixtures'],
180
- ['transcript', 'transcript', 'module', 'transcript.ts', 'pkg:github/principal-ai/agent-monitoring', 'parses session records + type guards'],
181
- ['paths', 'paths', 'module', 'paths.ts', 'pkg:github/principal-ai/agent-monitoring', 'extracts tool names + file paths'],
182
- ['reader', 'SessionReader', 'class', 'SessionReader.ts', 'pkg:github/principal-ai/agent-monitoring', 'normalizes a session into universal events', 'SessionReader.normalize', readerDetail],
183
- ['registry', 'supported-agents', 'module', 'supported-agents.ts', 'pkg:github/principal-ai/agent-monitoring', 'registry of supported agents (the shared seam)', 'registerAgent'],
184
- ]);
185
-
186
- const v2ReaderEdges = edges([
187
- ['transcript', 'reader', 'imports'],
188
- ['paths', 'reader', 'imports'],
189
- ['capture', 'reader', 'calls'],
190
- ['reader', 'registry', 'registers-into', ['supported-agents.ts']],
191
- // Consumer packages - cross-package edges leave the subgraph
192
- ['reader', 'trail-viewer-host', 'imports'],
193
- ['reader', 'core-sessions', 'imports'],
194
- ['reader', 'cli-session', 'imports'],
195
- ]);
196
-
197
- function V2ReaderDemo() {
198
- const [selected, setSelected] = useState<string | null>(null);
199
- const [selectedEdge, setSelectedEdge] = useState<SubsystemComponentEdge | null>(null);
200
- return (
201
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
202
- <SubsystemComponentGraph
203
- components={v2ReaderComponents}
204
- edges={v2ReaderEdges}
205
- onSelect={(id) => setSelected(id)}
206
- onEdgeSelect={(e) => setSelectedEdge(e)}
207
- />
208
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
209
- {selectedEdge
210
- ? `edge: ${selectedEdge.from} --${selectedEdge.mechanism}--> ${selectedEdge.to}${selectedEdge.refs?.length ? ` [refs: ${selectedEdge.refs.join(', ')}]` : ''}`
211
- : selected
212
- ? `selected: ${selected}`
213
- : 'click a component or edge to select it'}
214
- </div>
215
- </div>
216
- );
217
- }
218
-
219
- export const V2ReaderSubsystem: Story = {
220
- render: () => <V2ReaderDemo />,
221
- };
222
-
223
- // ---------------------------------------------------------------------------
224
- // Empty state
225
- // ---------------------------------------------------------------------------
226
- export const Empty: Story = {
227
- render: () => (
228
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
229
- <SubsystemComponentGraph components={[]} edges={[]} />
230
- </div>
231
- ),
232
- };
233
-
234
- // ---------------------------------------------------------------------------
235
- // Single package (no consumers) - the investigate-and-pin pattern.
236
- // Conveys the idea via LAYERS: readers (input) → accumulator (processing).
237
- // ---------------------------------------------------------------------------
238
- const investigateOnlyComponents: SubsystemComponent[] = [
239
- {
240
- id: 'v1',
241
- name: 'V1EventBridgeProcessor',
242
- kind: 'class',
243
- file: 'src/event-processing/V1EventBridge.ts',
244
- purl: 'pkg:github/principal-ai/agent-monitoring',
245
- purpose: 'normalizes V1 DB rows into universal events',
246
- symbol: 'V1EventBridgeProcessor',
247
- },
248
- {
249
- id: 'v2',
250
- name: 'V2EventBridgeProcessor',
251
- kind: 'class',
252
- file: 'src/event-processing/V2EventBridge.ts',
253
- purl: 'pkg:github/principal-ai/agent-monitoring',
254
- purpose: 'normalizes V2 durable events into universal events',
255
- symbol: 'V2EventBridgeProcessor',
256
- },
257
- {
258
- id: 'input',
259
- name: 'RepoNormalizedUniversalAgentSessionEvent',
260
- kind: 'type',
261
- file: 'types/RepoNormalizedUniversalAgentSessionEvent.ts',
262
- purl: 'pkg:github/principal-ai/agent-monitoring',
263
- purpose: 'the subsystem\u2019s input type — a repo-normalized universal event the readers produce and the accumulator consumes',
264
- symbol: 'RepoNormalizedUniversalAgentSessionEvent',
265
- detail: {
266
- kind: 'type',
267
- properties: [
268
- { name: 'eventType', type: 'NormalizedEventType' },
269
- { name: 'sessionId', type: 'string' },
270
- { name: 'timestamp', type: 'number' },
271
- ],
272
- usedBy: [{ nodeId: 'acc', name: 'accumulateToAgentSessionEvents', context: 'parameter_type' }],
273
- implementors: [],
274
- } satisfies GraphifyComponentDetail,
275
- },
276
- {
277
- id: 'acc',
278
- name: 'accumulateToAgentSessionEvents',
279
- kind: 'function',
280
- file: 'src/event-processing/accumulator.ts',
281
- purl: 'pkg:github/principal-ai/agent-monitoring',
282
- purpose: 'accumulates normalized events into agent session events',
283
- symbol: 'accumulateToAgentSessionEvents',
284
- },
285
- {
286
- id: 'out',
287
- name: 'AgentSessionEvent',
288
- kind: 'type',
289
- file: 'src/event-processing/accumulator.ts',
290
- purl: 'pkg:github/principal-ai/agent-monitoring',
291
- purpose: 'the subsystem\u2019s output type — an accumulated agent-session event',
292
- symbol: 'AgentSessionEvent',
293
- detail: {
294
- kind: 'type',
295
- properties: [
296
- { name: 'sessionName', type: 'string' },
297
- { name: 'operation', type: 'AgentSessionEventOperation' },
298
- { name: 'description', type: 'string' },
299
- ],
300
- usedBy: [{ nodeId: 'acc', name: 'accumulateToAgentSessionEvents', context: 'return_type' }],
301
- implementors: [],
302
- } satisfies GraphifyComponentDetail,
303
- },
304
- ];
305
-
306
- const investigateOnlyEdges = edges([
307
- // Concept-level data flow — the LLM's semantic intent.
308
- ['v1', 'input', 'produces'],
309
- ['v2', 'input', 'produces'],
310
- ['input', 'acc', 'feeds'],
311
- ['acc', 'out', 'produces'],
312
- ]);
313
-
314
- export const InvestigateOnly: Story = {
315
- render: () => (
316
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
317
- <SubsystemComponentGraph components={investigateOnlyComponents} edges={investigateOnlyEdges} />
318
- </div>
319
- ),
320
- };
321
-
322
- /** Same pipeline with a narrower `maxNodeWidth` (140) — long names wrap. */
323
- export const NarrowMaxWidth: Story = {
324
- render: () => (
325
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
326
- <SubsystemComponentGraph
327
- components={investigateOnlyComponents}
328
- edges={investigateOnlyEdges}
329
- maxNodeWidth={140}
330
- />
331
- </div>
332
- ),
333
- };
334
-
335
- // ---------------------------------------------------------------------------
336
- // Naming-convention wrap check — one node per common symbol convention.
337
- // ---------------------------------------------------------------------------
338
- const namingConventionComponents: SubsystemComponent[] = [
339
- {
340
- id: 'camel',
341
- name: 'accumulateToAgentSessionEvents',
342
- kind: 'function',
343
- file: 'src/event-processing/accumulator.ts',
344
- purl: 'pkg:github/principal-ai/agent-monitoring',
345
- symbol: 'accumulateToAgentSessionEvents',
346
- },
347
- {
348
- id: 'snake',
349
- name: 'repo_normalized_universal_event',
350
- kind: 'type',
351
- file: 'src/event-processing/repo_normalized.ts',
352
- purl: 'pkg:github/principal-ai/agent-monitoring',
353
- symbol: 'repo_normalized_universal_event',
354
- },
355
- {
356
- id: 'pascal',
357
- name: 'RepoNormalizedUniversalAgentSessionEvent',
358
- kind: 'class',
359
- file: 'src/event-processing/RepoNormalized.ts',
360
- purl: 'pkg:github/principal-ai/agent-monitoring',
361
- symbol: 'RepoNormalizedUniversalAgentSessionEvent',
362
- },
363
- {
364
- id: 'acronym',
365
- name: 'ProcessSSEStreamForEventToken',
366
- kind: 'function',
367
- file: 'src/event-processing/sse.ts',
368
- purl: 'pkg:github/principal-ai/agent-monitoring',
369
- symbol: 'ProcessSSEStreamForEventToken',
370
- },
371
- {
372
- id: 'method',
373
- name: 'normalize',
374
- kind: 'function',
375
- file: 'src/session/SessionReader.ts',
376
- purl: 'pkg:github/principal-ai/agent-monitoring',
377
- symbol: 'SessionReader.normalize',
378
- },
379
- {
380
- id: 'pkg',
381
- name: 'trail-viewer',
382
- kind: 'external',
383
- file: '',
384
- purl: 'pkg:npm/@principal-ai/trail-viewer',
385
- symbol: '',
386
- },
387
- ];
388
-
389
- const namingConventionEdges: SubsystemComponentEdge[] = [];
390
-
391
- /** Nodes with compact `maxNodeWidth` so the different conventions visibly wrap
392
- * at their word boundaries (camelCase, snake_case, PascalCase, acronyms). */
393
- export const NamingConventions: Story = {
394
- render: () => (
395
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
396
- <SubsystemComponentGraph
397
- components={namingConventionComponents}
398
- edges={namingConventionEdges}
399
- maxNodeWidth={180}
400
- />
401
- </div>
402
- ),
403
- };
404
-
405
- // ---------------------------------------------------------------------------
406
- // One node per GraphifyComponentDetail kind — what each looks like + drills down
407
- // ---------------------------------------------------------------------------
408
- const detailKindComponents: SubsystemComponent[] = [
409
- {
410
- id: 'detail-class',
411
- name: 'SessionReader',
412
- kind: 'class',
413
- file: 'src/session/SessionReader.ts',
414
- purl: 'pkg:github/principal-ai/agent-monitoring',
415
- purpose: 'class-like: owns outgoing method edges',
416
- symbol: '',
417
- detail: readerDetail,
418
- },
419
- {
420
- id: 'detail-method',
421
- name: 'normalize',
422
- kind: 'function',
423
- file: 'src/session/SessionReader.ts',
424
- purl: 'pkg:github/principal-ai/agent-monitoring',
425
- purpose: 'a class method — the specific thing this session focused on',
426
- symbol: 'SessionReader.normalize',
427
- detail: {
428
- kind: 'function',
429
- parameters: [{ name: 'session', type: 'SessionRecord' }],
430
- returnType: 'SessionEvent[]',
431
- callers: [{ nodeId: 'c1', name: 'capture-session', source_location: 'L120' }],
432
- callees: [{ nodeId: 'c2', name: 'toUniversalEvents', source_location: 'L64' }],
433
- } satisfies GraphifyComponentDetail,
434
- },
435
- {
436
- id: 'detail-fn',
437
- name: 'normalizeSession',
438
- kind: 'function',
439
- file: 'src/event-processing/normalize.ts',
440
- purl: 'pkg:github/principal-ai/agent-monitoring',
441
- purpose: 'function-like: label ends () with no method edges',
442
- symbol: 'normalizeSession',
443
- detail: {
444
- kind: 'function',
445
- parameters: [
446
- { name: 'session', type: 'SessionRecord' },
447
- { name: 'limit', type: 'number' },
448
- ],
449
- returnType: 'SessionEvent[]',
450
- callers: [{ nodeId: 'c1', name: 'SessionReader.normalize', source_location: 'L120' }],
451
- callees: [{ nodeId: 'c2', name: 'toUniversalEvents', source_location: 'L64' }],
452
- } satisfies GraphifyComponentDetail,
453
- },
454
- {
455
- id: 'detail-fn-rich',
456
- name: 'mergeSessions',
457
- kind: 'function',
458
- file: 'src/session/merge.ts',
459
- purl: 'pkg:github/principal-ai/agent-monitoring',
460
- purpose: 'multi-param signature — named, positional (graphify captures types only), union types, generic return',
461
- symbol: 'mergeSessions',
462
- detail: {
463
- kind: 'function',
464
- parameters: [
465
- { name: 'sessions', type: 'SessionRecord[]' },
466
- { type: 'MergeOptions' },
467
- { name: 'strategy', type: `'append' | 'replace' | 'skip'` },
468
- { name: 'onConflict', type: '((a: SessionRecord, b: SessionRecord) => SessionRecord)' },
469
- ],
470
- returnType: 'Promise<Map<string, SessionEvent[]>>',
471
- callers: [
472
- { nodeId: 'c1', name: 'capture-session', source_location: 'L88' },
473
- { nodeId: 'c3', name: 'backfill', source_location: 'L210' },
474
- ],
475
- callees: [{ nodeId: 'c2', name: 'toUniversalEvents', source_location: 'L64' }],
476
- } satisfies GraphifyComponentDetail,
477
- },
478
- {
479
- id: 'detail-fn-void',
480
- name: 'flush',
481
- kind: 'function',
482
- file: 'src/event-processing/sink.ts',
483
- purl: 'pkg:github/principal-ai/agent-monitoring',
484
- purpose: 'no parameters, no return type — the barest function signature',
485
- symbol: 'flush',
486
- detail: {
487
- kind: 'function',
488
- parameters: [],
489
- callers: [{ nodeId: 'c4', name: 'EventProcessor.dispose', source_location: 'L142' }],
490
- callees: [],
491
- } satisfies GraphifyComponentDetail,
492
- },
493
- {
494
- id: 'detail-class-rich',
495
- name: 'EventProcessor',
496
- kind: 'class',
497
- file: 'src/event-processing/EventProcessor.ts',
498
- purl: 'pkg:github/principal-ai/agent-monitoring',
499
- purpose: 'class with fully-typed members — method params + returns, field types, extends + implements',
500
- symbol: 'EventProcessor',
501
- detail: {
502
- kind: 'class',
503
- methods: [
504
- { nodeId: 'rm1', name: 'process', parameters: [{ type: 'RawEvent' }, { type: 'ProcessingOptions' }], returnType: 'ProcessedEvent' },
505
- { nodeId: 'rm2', name: 'batch', parameters: [{ type: 'RawEvent[]' }], returnType: 'Promise<ProcessedEvent[]>' },
506
- { nodeId: 'rm3', name: 'onError', parameters: [{ type: 'Error' }] },
507
- { nodeId: 'rm4', name: 'dispose' },
508
- ],
509
- properties: [
510
- { name: 'queue', type: 'RawEvent[]' },
511
- { name: 'options', type: 'Required<ProcessingOptions>' },
512
- { name: 'retryLimit', type: 'number' },
513
- ],
514
- extends: ['BaseProcessor'],
515
- implements: ['Disposable', 'EventEmitterLike'],
516
- instantiations: [
517
- { nodeId: 'x1', name: 'main' },
518
- { nodeId: 'x2', name: 'worker-pool' },
519
- ],
520
- references: [{ nodeId: 'x3', name: 'pipeline', context: 'type' }],
521
- } satisfies GraphifyComponentDetail,
522
- },
523
- {
524
- id: 'detail-type',
525
- name: 'SessionRecord',
526
- kind: 'type',
527
- file: 'src/session/transcript.ts',
528
- purl: 'pkg:github/principal-ai/agent-monitoring',
529
- purpose: 'type-like: revealed by incoming implements edges',
530
- symbol: 'SessionRecord',
531
- detail: {
532
- kind: 'type',
533
- properties: [
534
- { name: 'id', type: 'string' },
535
- { name: 'admittedSeq', type: 'number' },
536
- ],
537
- usedBy: [{ nodeId: 'u1', name: 'normalizeSession', context: 'type' }],
538
- implementors: ['SessionReaderLike'],
539
- } satisfies GraphifyComponentDetail,
540
- },
541
- {
542
- id: 'detail-module',
543
- name: 'CodexRolloutRecord',
544
- kind: 'type',
545
- file: 'src/session/transcript.ts',
546
- purl: 'pkg:github/principal-ai/agent-monitoring',
547
- purpose: 'a type symbol that lives in the transcript module; the node is the symbol, the file is its location',
548
- symbol: 'CodexRolloutRecord',
549
- detail: {
550
- kind: 'type',
551
- properties: [
552
- { name: 'type', type: 'string' },
553
- { name: 'id', type: 'string' },
554
- ],
555
- usedBy: [{ nodeId: 'u1', name: 'isCodexRolloutRecord', context: 'type' }],
556
- implementors: [],
557
- } satisfies GraphifyComponentDetail,
558
- },
559
- {
560
- id: 'detail-external',
561
- // name = the package's name after the namespace; namespace shown above.
562
- name: 'trail-viewer',
563
- kind: 'external',
564
- file: '',
565
- purl: 'pkg:npm/@principal-ai/trail-viewer',
566
- purpose: 'an npm package consumer — the whole package as a node',
567
- symbol: '',
568
- detail: {
569
- kind: 'external',
570
- label: 'pkg:npm/@principal-ai/trail-viewer',
571
- } satisfies GraphifyComponentDetail,
572
- },
573
- ];
574
-
575
- const detailKindEdges: SubsystemComponentEdge[] = [];
576
-
577
- function DetailKindsDemo() {
578
- const [selected, setSelected] = useState<string | null>(null);
579
- return (
580
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
581
- <SubsystemComponentGraph
582
- components={detailKindComponents}
583
- edges={detailKindEdges}
584
- onSelect={(id) => setSelected(id)}
585
- />
586
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
587
- {selected ? `selected: ${selected}` : 'click a component to see its GraphifyComponentDetail'}
588
- </div>
589
- </div>
590
- );
591
- }
592
-
593
- export const DetailKinds: Story = {
594
- render: () => <DetailKindsDemo />,
595
- };
596
-
597
- // ---------------------------------------------------------------------------
598
- // Kind variations — one column per kind (class / function / type / module /
599
- // external), rows going bare → detailed. Click a node to see its declaration
600
- // panel; type names inside it are clickable when they match another node here.
601
- // ---------------------------------------------------------------------------
602
- const variationPurl = 'pkg:github/principal-ai/agent-monitoring';
603
-
604
- const kindVariationComponents: SubsystemComponent[] = [
605
- // --- class: bare → members only → relationships only
606
- {
607
- id: 'cls-bare',
608
- name: 'SessionStore',
609
- kind: 'class',
610
- file: 'src/session/SessionStore.ts',
611
- purl: variationPurl,
612
- purpose: 'no drill-down — renders a plain `class SessionStore`',
613
- symbol: 'SessionStore',
614
- layer: 1,
615
- },
616
- {
617
- id: 'cls-members',
618
- name: 'Transcoder',
619
- kind: 'class',
620
- file: 'src/session/Transcoder.ts',
621
- purl: variationPurl,
622
- purpose: 'members only — methods with typed params + returns, a typed field',
623
- symbol: 'Transcoder',
624
- layer: 1,
625
- detail: {
626
- kind: 'class',
627
- methods: [
628
- { nodeId: 'tm1', name: 'encode', parameters: [{ type: 'RawFrame' }], returnType: 'Uint8Array' },
629
- { nodeId: 'tm2', name: 'decode', parameters: [{ type: 'Uint8Array' }], returnType: 'RawFrame' },
630
- { nodeId: 'tm3', name: 'reset' },
631
- ],
632
- properties: [{ name: 'bufferSize', type: 'number' }],
633
- extends: [],
634
- implements: [],
635
- instantiations: [],
636
- references: [],
637
- } satisfies GraphifyComponentDetail,
638
- },
639
- {
640
- id: 'cls-relations',
641
- name: 'HttpTransport',
642
- kind: 'class',
643
- file: 'src/transport/HttpTransport.ts',
644
- purl: variationPurl,
645
- purpose: 'relationships only — extends + implements, constructed-by comment; empty body elides the braces',
646
- symbol: 'HttpTransport',
647
- layer: 1,
648
- detail: {
649
- kind: 'class',
650
- methods: [],
651
- properties: [],
652
- extends: ['BaseTransport'],
653
- implements: ['Transport'],
654
- instantiations: [{ nodeId: 'x1', name: 'main' }],
655
- references: [],
656
- } satisfies GraphifyComponentDetail,
657
- },
658
-
659
- // --- function: bare → signature only → signature + call relationships
660
- {
661
- id: 'fn-bare',
662
- name: 'bootstrap',
663
- kind: 'function',
664
- file: 'src/bootstrap.ts',
665
- purl: variationPurl,
666
- purpose: 'no drill-down — renders a plain `function bootstrap()`',
667
- symbol: 'bootstrap',
668
- layer: 2,
669
- },
670
- {
671
- id: 'fn-signature',
672
- name: 'normalizeSession',
673
- kind: 'function',
674
- file: 'src/event-processing/normalize.ts',
675
- purl: variationPurl,
676
- purpose: 'signature only — named + positional (type-only) params, array return; no callers/callees comments',
677
- symbol: 'normalizeSession',
678
- layer: 2,
679
- detail: {
680
- kind: 'function',
681
- parameters: [
682
- { name: 'session', type: 'SessionRecord' },
683
- { type: 'NormalizeOptions' },
684
- ],
685
- returnType: 'SessionEvent[]',
686
- callers: [],
687
- callees: [],
688
- } satisfies GraphifyComponentDetail,
689
- },
690
- {
691
- id: 'fn-calls',
692
- name: 'mergeSessions',
693
- kind: 'function',
694
- file: 'src/session/merge.ts',
695
- purl: variationPurl,
696
- purpose: 'signature + call relationships — union-typed param, generic return, called-by / calls trailing comments',
697
- symbol: 'mergeSessions',
698
- layer: 2,
699
- detail: {
700
- kind: 'function',
701
- parameters: [
702
- { name: 'sessions', type: 'SessionRecord[]' },
703
- { name: 'strategy', type: `'append' | 'replace'` },
704
- ],
705
- returnType: 'Promise<SessionEvent[]>',
706
- callers: [{ nodeId: 'c1', name: 'capture-session', source_location: 'L88' }],
707
- callees: [{ nodeId: 'c2', name: 'toUniversalEvents', source_location: 'L64' }],
708
- } satisfies GraphifyComponentDetail,
709
- },
710
-
711
- // --- type: bare → fields only → fields + implementors + used-by
712
- {
713
- id: 'ty-bare',
714
- name: 'RawFrame',
715
- kind: 'type',
716
- file: 'src/session/RawFrame.ts',
717
- purl: variationPurl,
718
- purpose: 'no drill-down — renders a plain `interface RawFrame`',
719
- symbol: 'RawFrame',
720
- layer: 3,
721
- },
722
- {
723
- id: 'ty-fields',
724
- name: 'SessionRecord',
725
- kind: 'type',
726
- file: 'src/session/transcript.ts',
727
- purl: variationPurl,
728
- purpose: 'fields only — typed interface body, nothing else',
729
- symbol: 'SessionRecord',
730
- layer: 3,
731
- detail: {
732
- kind: 'type',
733
- properties: [
734
- { name: 'id', type: 'string' },
735
- { name: 'admittedSeq', type: 'number' },
736
- ],
737
- usedBy: [],
738
- implementors: [],
739
- } satisfies GraphifyComponentDetail,
740
- },
741
- {
742
- id: 'ty-full',
743
- name: 'Transport',
744
- kind: 'type',
745
- file: 'src/transport/Transport.ts',
746
- purl: variationPurl,
747
- purpose: 'full — fields + implemented-by (clicks through to HttpTransport) + used-by comments',
748
- symbol: 'Transport',
749
- layer: 3,
750
- detail: {
751
- kind: 'type',
752
- properties: [{ name: 'name', type: 'string' }],
753
- usedBy: [{ nodeId: 'u1', name: 'main', context: 'parameter_type' }],
754
- implementors: ['HttpTransport'],
755
- } satisfies GraphifyComponentDetail,
756
- },
757
-
758
- // --- module: bare → exports only → exports + imports
759
- {
760
- id: 'mod-bare',
761
- name: 'transcript',
762
- kind: 'module',
763
- file: 'src/session/transcript.ts',
764
- purl: variationPurl,
765
- purpose: 'no drill-down — symbol-less module named from its file basename',
766
- symbol: '',
767
- layer: 4,
768
- },
769
- {
770
- id: 'mod-exports',
771
- name: 'paths',
772
- kind: 'module',
773
- file: 'src/session/paths.ts',
774
- purl: variationPurl,
775
- purpose: 'exports only — export statement + defines comment',
776
- symbol: '',
777
- layer: 4,
778
- detail: {
779
- kind: 'module',
780
- exports: ['extractToolName', 'extractFilePath'],
781
- imports: [],
782
- symbols: ['extractToolName', 'extractFilePath'],
783
- } satisfies GraphifyComponentDetail,
784
- },
785
- {
786
- id: 'mod-full',
787
- name: 'index',
788
- kind: 'module',
789
- file: 'src/index.ts',
790
- purl: variationPurl,
791
- purpose: 'full — import statements + re-export statement + defines comment',
792
- symbol: '',
793
- layer: 4,
794
- detail: {
795
- kind: 'module',
796
- exports: ['SessionReader', 'SessionStore'],
797
- imports: [{ nodeId: 'i1', name: 'transcript', relation: 'imports_from' }],
798
- symbols: ['SessionReader', 'SessionStore'],
799
- } satisfies GraphifyComponentDetail,
800
- },
801
-
802
- // --- external: bare → labeled
803
- {
804
- id: 'ext-bare',
805
- name: 'left-pad',
806
- kind: 'external',
807
- file: '',
808
- purl: 'pkg:npm/left-pad',
809
- purpose: 'no drill-down — renders a plain `external left-pad`',
810
- symbol: '',
811
- layer: 5,
812
- },
813
- {
814
- id: 'ext-label',
815
- name: 'trail-viewer',
816
- kind: 'external',
817
- file: '',
818
- purl: 'pkg:npm/@principal-ai/trail-viewer',
819
- purpose: 'labeled — the full purl as a quoted string literal',
820
- symbol: '',
821
- layer: 5,
822
- detail: {
823
- kind: 'external',
824
- label: 'pkg:npm/@principal-ai/trail-viewer',
825
- } satisfies GraphifyComponentDetail,
826
- },
827
- ];
828
-
829
- const kindVariationEdges: SubsystemComponentEdge[] = [];
830
-
831
- function KindVariationsDemo() {
832
- const [selected, setSelected] = useState<string | null>(null);
833
- return (
834
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
835
- <SubsystemComponentGraph
836
- components={kindVariationComponents}
837
- edges={kindVariationEdges}
838
- onSelect={(id) => setSelected(id)}
839
- />
840
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
841
- columns: class · function · type · module · external — each goes bare → detailed
842
- {selected ? ` · selected: ${selected}` : ''}
843
- </div>
844
- </div>
845
- );
846
- }
847
-
848
- export const KindVariations: Story = {
849
- render: () => <KindVariationsDemo />,
850
- };
851
-
852
- // ---------------------------------------------------------------------------
853
- // Minimal (pre-graphify) vs Resolved (post-graphify) — the SAME subsystem,
854
- // showing what the LLM emits (no detail) and what graphify enrichment adds.
855
- // ---------------------------------------------------------------------------
856
-
857
- /** The minimal LLM-authored substrate: symbols only, no `detail`. */
858
- const minimalComponents = components([
859
- ['reader', 'SessionReader', 'class', 'SessionReader.ts', 'pkg:github/principal-ai/agent-monitoring', 'normalizes a session into universal events', 'SessionReader'],
860
- ['normalize', 'normalize', 'function', 'SessionReader.ts', 'pkg:github/principal-ai/agent-monitoring', 'maps a session into universal events', 'SessionReader.normalize'],
861
- ['record', 'SessionRecord', 'type', 'transcript.ts', 'pkg:github/principal-ai/agent-monitoring', 'the parsed codex session record', 'SessionRecord'],
862
- ['transcript', 'transcript', 'module', 'transcript.ts', 'pkg:github/principal-ai/agent-monitoring', 'parses session records + type guards', 'transcript'],
863
- ]);
864
-
865
- const sharedEdges = edges([
866
- ['transcript', 'record', 'defines'],
867
- ['reader', 'normalize', 'method'],
868
- ['normalize', 'record', 'references'],
869
- ]);
870
-
871
- /** The same subsystem after `resolveSubsystemToGraphify` populates `detail`. */
872
- const resolvedComponents: SubsystemComponent[] = [
873
- { ...minimalComponents[0], detail: readerDetail },
874
- {
875
- ...minimalComponents[1],
876
- detail: {
877
- kind: 'function',
878
- parameters: [{ name: 'session', type: 'SessionRecord' }],
879
- returnType: 'SessionEvent[]',
880
- callers: [{ nodeId: 'c1', name: 'capture-session', source_location: 'L120' }],
881
- callees: [{ nodeId: 'c2', name: 'toUniversalEvents', source_location: 'L64' }],
882
- } satisfies GraphifyComponentDetail,
883
- },
884
- {
885
- ...minimalComponents[2],
886
- detail: {
887
- kind: 'type',
888
- properties: [
889
- { name: 'id', type: 'string' },
890
- { name: 'type', type: 'string' },
891
- ],
892
- usedBy: [{ nodeId: 'u1', name: 'normalize', context: 'type' }],
893
- implementors: ['SessionReaderLike'],
894
- } satisfies GraphifyComponentDetail,
895
- },
896
- {
897
- ...minimalComponents[3],
898
- detail: {
899
- kind: 'module',
900
- exports: ['CodexRolloutRecord', 'CodexSessionMeta'],
901
- imports: [{ nodeId: 'i1', name: 'paths', relation: 'imports_from' }],
902
- symbols: ['CodexRolloutRecord', 'CodexSessionMeta'],
903
- } satisfies GraphifyComponentDetail,
904
- },
905
- ];
906
-
907
- function MinimalVsResolvedDemo({ resolved }: { resolved: boolean }) {
908
- const [selected, setSelected] = useState<string | null>(null);
909
- return (
910
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
911
- <SubsystemComponentGraph
912
- components={resolved ? resolvedComponents : minimalComponents}
913
- edges={sharedEdges}
914
- onSelect={(id) => setSelected(id)}
915
- />
916
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
917
- {resolved
918
- ? 'post-graphify: click a component to see the enriched GraphifyComponentDetail'
919
- : 'pre-graphify: LLM-authored symbols only — no detail yet'}
920
- </div>
921
- </div>
922
- );
923
- }
924
-
925
- export const MinimalPreGraphify: Story = {
926
- render: () => <MinimalVsResolvedDemo resolved={false} />,
927
- };
928
-
929
- export const ResolvedPostGraphify: Story = {
930
- render: () => <MinimalVsResolvedDemo resolved />,
931
- };
932
-
933
- // ---------------------------------------------------------------------------
934
- // Investigation-derived subsystem — grok session 019fd2a9 (t3code)
935
- // Read-only analysis of "provider / event threading". Components are occupied
936
- // (analyzed, not edited) — no code touched, but a coherent concept was worked.
937
- // ---------------------------------------------------------------------------
938
- const investigationComponents: SubsystemComponent[] = [
939
- {
940
- id: 'adapter',
941
- name: 'OpenCodeAdapter',
942
- kind: 'module',
943
- file: 'apps/server/src/provider/Layers/OpenCodeAdapter.ts',
944
- purl: 'pkg:github/t3code/t3code',
945
- purpose: 'adapts opencode session/threads + events to the t3 runtime',
946
- symbol: 'makeOpenCodeAdapter',
947
- capture: 'analyzed',
948
- detail: {
949
- kind: 'module',
950
- exports: ['makeOpenCodeAdapter', 'OpenCodeAdapterLiveOptions'],
951
- imports: [{ nodeId: 'i1', name: 'orchestration', relation: 'imports_from' }],
952
- symbols: ['makeOpenCodeAdapter', 'isOpenCodeNotFound', 'OpenCodeSessionContext'],
953
- } satisfies GraphifyComponentDetail,
954
- },
955
- {
956
- id: 'ingestion',
957
- name: 'ProviderRuntimeIngestion',
958
- kind: 'module',
959
- file: 'apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts',
960
- purl: 'pkg:github/t3code/t3code',
961
- purpose: 'ingests provider events into the runtime',
962
- symbol: 'ProviderRuntimeIngestion',
963
- capture: 'analyzed',
964
- },
965
- {
966
- id: 'contracts',
967
- name: 'orchestration',
968
- kind: 'module',
969
- file: 'packages/contracts/src/orchestration.ts',
970
- purl: 'pkg:github/t3code/t3code',
971
- purpose: 'contracts for orchestration/providers',
972
- symbol: 'ORCHESTRATION_WS_METHODS',
973
- capture: 'analyzed',
974
- },
975
- ];
976
-
977
- const investigationEdges = edges([
978
- ['adapter', 'contracts', 'imports_from'],
979
- ['ingestion', 'adapter', 'uses'],
980
- ['ingestion', 'contracts', 'references'],
981
- ]);
982
-
983
- function InvestigationDemo() {
984
- const [selected, setSelected] = useState<string | null>(null);
985
- return (
986
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
987
- <SubsystemComponentGraph
988
- components={investigationComponents}
989
- edges={investigationEdges}
990
- onSelect={(id) => setSelected(id)}
991
- />
992
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
993
- read-only investigation snapshot (grok 019fd2a9) — components analyzed, not edited
994
- {selected ? ` · selected: ${selected}` : ''}
995
- </div>
996
- </div>
997
- );
998
- }
999
-
1000
- export const InvestigationDerived: Story = {
1001
- render: () => <InvestigationDemo />,
1002
- };
1003
-
1004
- // ---------------------------------------------------------------------------
1005
- // Mermaid diagram rendering pipeline (industry-themed-markdown)
1006
- // ---------------------------------------------------------------------------
1007
- const mermaidPurl = 'pkg:github/principal-ade/industry-themed-markdown';
1008
-
1009
- const mermaidComponents: SubsystemComponent[] = [
1010
- {
1011
- id: 'input',
1012
- name: 'MarkdownContent',
1013
- kind: 'type',
1014
- file: 'industryMarkdown/components/IndustryMarkdownSlide.tsx',
1015
- purl: mermaidPurl,
1016
- purpose: 'raw markdown string — the slide\u2019s input',
1017
- symbol: 'MarkdownContent',
1018
- },
1019
- {
1020
- id: 'slide',
1021
- name: 'IndustryMarkdownSlide',
1022
- kind: 'class',
1023
- file: 'industryMarkdown/components/IndustryMarkdownSlide.tsx',
1024
- purl: mermaidPurl,
1025
- purpose: 'orchestrator — parses markdown into chunks, maps mermaid chunks to diagrams',
1026
- symbol: 'IndustryMarkdownSlide',
1027
- },
1028
- {
1029
- id: 'chunk',
1030
- name: 'MermaidChunk',
1031
- kind: 'type',
1032
- file: 'industryMarkdown/types/customMarkdownChunks.ts',
1033
- purl: mermaidPurl,
1034
- purpose: 'parsed chunk — code string + id, the slide\u2019s output per mermaid block',
1035
- symbol: 'MermaidChunk',
1036
- },
1037
- {
1038
- id: 'lazy',
1039
- name: 'IndustryLazyMermaidDiagram',
1040
- kind: 'class',
1041
- file: 'industryMarkdown/components/IndustryLazyMermaidDiagram.tsx',
1042
- purl: mermaidPurl,
1043
- purpose: 'IntersectionObserver lazy-loading wrapper \u2014 defers render until scrolled into view',
1044
- symbol: 'IndustryLazyMermaidDiagram',
1045
- },
1046
- {
1047
- id: 'diagram',
1048
- name: 'IndustryMermaidDiagram',
1049
- kind: 'class',
1050
- file: 'industryMarkdown/components/IndustryMermaidDiagram.tsx',
1051
- purl: mermaidPurl,
1052
- purpose: 'core renderer \u2014 picks engine (beautiful-mermaid vs mermaid.js), renders themed SVG',
1053
- symbol: 'IndustryMermaidDiagram',
1054
- },
1055
- {
1056
- id: 'helpers',
1057
- name: 'beautifulMermaid',
1058
- kind: 'module',
1059
- file: 'industryMarkdown/utils/beautifulMermaid.ts',
1060
- purl: mermaidPurl,
1061
- purpose: 'engine detection, theme\u2192options mapping, SVG post-processing',
1062
- symbol: 'beautifulMermaid',
1063
- },
1064
- ];
1065
-
1066
- const mermaidEdges = edges([
1067
- ['input', 'slide', 'feeds'],
1068
- ['slide', 'chunk', 'produces'],
1069
- ['chunk', 'lazy', 'feeds'],
1070
- ['lazy', 'diagram', 'wraps'],
1071
- ['diagram', 'helpers', 'uses'],
1072
- ]);
1073
-
1074
- function MermaidDemo() {
1075
- const [selected, setSelected] = useState<string | null>(null);
1076
- return (
1077
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
1078
- <SubsystemComponentGraph
1079
- components={mermaidComponents}
1080
- edges={mermaidEdges}
1081
- onSelect={(id) => setSelected(id)}
1082
- />
1083
- <div style={{ marginTop: 8, fontFamily: 'monospace', fontSize: 12, color: '#aaa' }}>
1084
- mermaid diagram rendering pipeline — lazy → render → zoom → modal
1085
- {selected ? ` · selected: ${selected}` : ''}
1086
- </div>
1087
- </div>
1088
- );
1089
- }
1090
-
1091
- export const MermaidPipeline: Story = {
1092
- render: () => <MermaidDemo />,
1093
- };
1094
-
1095
- // ---------------------------------------------------------------------------
1096
- // Multi-repo: two repos → two sidebar trees, one per repo, each under its own
1097
- // owner-avatar + repo-name header. Exercises buildRepoGroups grouping,
1098
- // cross-repo edges (external stub targets), and per-tree selection.
1099
- // ---------------------------------------------------------------------------
1100
- const coreLibPurl = 'pkg:github/principal-ai/principal-view-core-library';
1101
- const graphifyPurl = 'pkg:github/Graphify-Labs/graphify';
1102
-
1103
- const multiRepoComponents = components([
1104
- ['resolver', 'resolve.ts', 'module', 'packages/react/src/graphify/resolve.ts', coreLibPurl, 'consumer-side resolution mirroring graphify rewire tiers', 'createGraphifyTypeResolver'],
1105
- ['reftypes', 'consolidated.ts', 'module', 'packages/react/src/graphify/consolidated.ts', coreLibPurl, 'drill-down payload types carrying ref.nodeId', 'GraphifyParamInfo'],
1106
- ['detail', 'ComponentDeclaration.tsx', 'module', 'packages/react/src/subsystem/ComponentDeclaration.tsx', coreLibPurl, 'declaration panel rendering the selected component as code, with clickable type tokens', 'ComponentDeclaration'],
1107
- ['engine', 'engine.py', 'module', 'graphify/extractors/engine.py', graphifyPurl, 'tree-sitter walk emitting references[parameter_type] edges + sourceless stubs', 'ensure_named_node'],
1108
- ['rewire', 'extract.py', 'module', 'graphify/extract.py', graphifyPurl, 'corpus pass folding unique-label stubs onto definitions', '_rewire_unique_stub_nodes'],
1109
- ]);
1110
-
1111
- const multiRepoEdges = edges([
1112
- ['detail', 'reftypes', 'imports'],
1113
- ['resolver', 'reftypes', 'imports'],
1114
- ['resolver', 'engine', 'references'],
1115
- ['rewire', 'resolver', 'calls'],
1116
- ]);
1117
-
1118
- function MultiRepoDemo() {
1119
- return (
1120
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
1121
- <SubsystemComponentGraph
1122
- title="Type-ref resolution across repos"
1123
- description="Two repos → two file trees. Each tree is scoped to its repo's files and headed by the owner avatar + repo name. Cross-repo edges land on external stubs."
1124
- components={multiRepoComponents}
1125
- edges={multiRepoEdges}
1126
- />
1127
- </div>
1128
- );
1129
- }
1130
-
1131
- export const MultiRepoTrees: Story = {
1132
- render: () => <MultiRepoDemo />,
1133
- };
1134
-
1135
- // ---------------------------------------------------------------------------
1136
- // Declaration line open — Pierre snippet/file views + declarationRef.
1137
- // Click the ComponentDeclaration node → toggle file → click path or L251.
1138
- // ---------------------------------------------------------------------------
1139
- const storyFileContents: Record<string, string> = {
1140
- 'packages/react/src/subsystem/ComponentDeclaration.tsx': componentDeclarationSource,
1141
- 'packages/react/src/graphify/resolve.ts': resolveSource,
1142
- };
1143
-
1144
- const declarationOpenComponents: SubsystemComponent[] = [
1145
- {
1146
- id: 'detail',
1147
- name: 'ComponentDeclaration',
1148
- kind: 'module',
1149
- file: 'packages/react/src/subsystem/ComponentDeclaration.tsx',
1150
- purl: 'pkg:github/principal-ai/principal-view-core-library',
1151
- purpose: 'declaration panel — click file or L251 to open the drawer at the export line',
1152
- symbol: 'ComponentDeclaration',
1153
- declarationRef: {
1154
- file: 'packages/react/src/subsystem/ComponentDeclaration.tsx',
1155
- startLine: 251,
1156
- lineHash: 'storybook-placeholder',
1157
- capturedAt: new Date(0).toISOString(),
1158
- },
1159
- },
1160
- {
1161
- id: 'resolver',
1162
- name: 'resolve.ts',
1163
- kind: 'module',
1164
- file: 'packages/react/src/graphify/resolve.ts',
1165
- purl: 'pkg:github/principal-ai/principal-view-core-library',
1166
- purpose: 'graphify type-ref resolver (second file for tree navigation)',
1167
- symbol: 'resolveGraphifyTypeRef',
1168
- declarationRef: {
1169
- file: 'packages/react/src/graphify/resolve.ts',
1170
- startLine: 1,
1171
- lineHash: 'storybook-placeholder',
1172
- capturedAt: new Date(0).toISOString(),
1173
- },
1174
- },
1175
- ];
1176
-
1177
- function readStoryFile(path: string): Promise<string> {
1178
- const content = storyFileContents[path];
1179
- if (content == null) {
1180
- return Promise.reject(new Error(`No story fixture for ${path}`));
1181
- }
1182
- return Promise.resolve(content);
1183
- }
1184
-
1185
- function DeclarationLineOpenDemo() {
1186
- const renderFileViewer = (file: string, opts?: SubsystemOpenFileOptions) => {
1187
- const startLine = opts?.startLine;
1188
- if (startLine != null) {
1189
- return (
1190
- <PierreSnippetView
1191
- filePath={file}
1192
- fileName={file.split('/').pop() ?? file}
1193
- startLine={startLine}
1194
- endLine={startLine}
1195
- focusLine={startLine}
1196
- contextLines={40}
1197
- readFile={readStoryFile}
1198
- />
1199
- );
1200
- }
1201
- return (
1202
- <PierreFileView
1203
- filePath={file}
1204
- fileName={file.split('/').pop() ?? file}
1205
- readFile={readStoryFile}
1206
- />
1207
- );
1208
- };
1209
-
1210
- return (
1211
- <div style={{ width: '100%', height: '100vh', display: 'flex', flexDirection: 'column' }}>
1212
- <SubsystemComponentGraph
1213
- title="Declaration line open (Storybook)"
1214
- description="Uses bundled ?raw fixtures + PierreSnippetView from this package. Select ComponentDeclaration, toggle file, click the path or L251."
1215
- components={declarationOpenComponents}
1216
- edges={[]}
1217
- renderFileViewer={renderFileViewer}
1218
- />
1219
- </div>
1220
- );
1221
- }
1222
-
1223
- export const DeclarationLineOpen: Story = {
1224
- render: () => <DeclarationLineOpenDemo />,
1225
- };