@principal-ai/subsystems-react 0.21.0 → 0.22.0

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 (267) hide show
  1. package/dist/graphify/consolidated.d.ts +5 -24
  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/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/pierre/PierreSnippetView.d.ts.map +1 -1
  10. package/dist/pierre/PierreSnippetView.js +4 -19
  11. package/dist/pierre/PierreSnippetView.js.map +1 -1
  12. package/dist/pierre/PierreWalkthroughCodeView.d.ts.map +1 -1
  13. package/dist/pierre/PierreWalkthroughCodeView.js +20 -3
  14. package/dist/pierre/PierreWalkthroughCodeView.js.map +1 -1
  15. package/dist/pierre/constructColors.d.ts.map +1 -1
  16. package/dist/pierre/constructColors.js +0 -5
  17. package/dist/pierre/constructColors.js.map +1 -1
  18. package/dist/pierre/index.d.ts +1 -1
  19. package/dist/pierre/index.d.ts.map +1 -1
  20. package/dist/pierre/index.js +1 -1
  21. package/dist/pierre/index.js.map +1 -1
  22. package/dist/pierre/sliceSnippet.d.ts +6 -0
  23. package/dist/pierre/sliceSnippet.d.ts.map +1 -1
  24. package/dist/pierre/sliceSnippet.js +25 -0
  25. package/dist/pierre/sliceSnippet.js.map +1 -1
  26. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts.map +1 -1
  27. package/dist/stories/Subsystem/ComponentGraph/fixtures.js +0 -3
  28. package/dist/stories/Subsystem/ComponentGraph/fixtures.js.map +1 -1
  29. package/dist/subsystem/formatDeclaration.d.ts.map +1 -1
  30. package/dist/subsystem/formatDeclaration.js +0 -15
  31. package/dist/subsystem/formatDeclaration.js.map +1 -1
  32. package/dist/subsystem/model.d.ts +61 -22
  33. package/dist/subsystem/model.d.ts.map +1 -1
  34. package/dist/subsystem/model.js +186 -63
  35. package/dist/subsystem/model.js.map +1 -1
  36. package/dist/subsystem/nodes.d.ts +3 -4
  37. package/dist/subsystem/nodes.d.ts.map +1 -1
  38. package/dist/subsystem/nodes.js +5 -6
  39. package/dist/subsystem/nodes.js.map +1 -1
  40. package/dist/utils/elkLayout.d.ts +6 -4
  41. package/dist/utils/elkLayout.d.ts.map +1 -1
  42. package/dist/utils/elkLayout.js +144 -54
  43. package/dist/utils/elkLayout.js.map +1 -1
  44. package/package.json +3 -3
  45. package/src/graphify/consolidated.ts +4 -26
  46. package/src/graphify/index.ts +0 -2
  47. package/src/index.ts +0 -2
  48. package/src/pierre/PierreSnippetView.tsx +4 -18
  49. package/src/pierre/PierreWalkthroughCodeView.tsx +39 -3
  50. package/src/pierre/constructColors.test.ts +1 -2
  51. package/src/pierre/constructColors.ts +0 -5
  52. package/src/pierre/index.ts +1 -1
  53. package/src/pierre/sliceSnippet.test.ts +44 -1
  54. package/src/pierre/sliceSnippet.ts +28 -0
  55. package/src/stories/Subsystem/ComponentDeclarationAudit.stories.tsx +0 -31
  56. package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +2 -46
  57. package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +9 -24
  58. package/src/stories/Subsystem/ComponentGraph/DetailPanel.stories.tsx +2 -2
  59. package/src/stories/Subsystem/ComponentGraph/Modules.stories.tsx +287 -0
  60. package/src/stories/Subsystem/ComponentGraph/Processes.stories.tsx +1 -1
  61. package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +6 -6
  62. package/src/stories/Subsystem/ComponentGraph/fixtures.ts +0 -3
  63. package/src/subsystem/formatDeclaration.ts +0 -19
  64. package/src/subsystem/model.test.ts +190 -9
  65. package/src/subsystem/model.ts +219 -73
  66. package/src/subsystem/nodes.tsx +6 -6
  67. package/src/utils/elkLayout.ts +148 -58
  68. package/dist/components/ConfigurationSelector.d.ts +0 -35
  69. package/dist/components/ConfigurationSelector.d.ts.map +0 -1
  70. package/dist/components/ConfigurationSelector.js +0 -63
  71. package/dist/components/ConfigurationSelector.js.map +0 -1
  72. package/dist/components/GraphRenderer.d.ts +0 -295
  73. package/dist/components/GraphRenderer.d.ts.map +0 -1
  74. package/dist/components/GraphRenderer.js +0 -2008
  75. package/dist/components/GraphRenderer.js.map +0 -1
  76. package/dist/components/MultiCanvasRenderer.d.ts +0 -75
  77. package/dist/components/MultiCanvasRenderer.d.ts.map +0 -1
  78. package/dist/components/MultiCanvasRenderer.js +0 -203
  79. package/dist/components/MultiCanvasRenderer.js.map +0 -1
  80. package/dist/components/NodeTooltip.d.ts +0 -24
  81. package/dist/components/NodeTooltip.d.ts.map +0 -1
  82. package/dist/components/NodeTooltip.js +0 -160
  83. package/dist/components/NodeTooltip.js.map +0 -1
  84. package/dist/components/SelectionSidebar.d.ts +0 -18
  85. package/dist/components/SelectionSidebar.d.ts.map +0 -1
  86. package/dist/components/SelectionSidebar.js +0 -190
  87. package/dist/components/SelectionSidebar.js.map +0 -1
  88. package/dist/components/SequenceDiagramRenderer.d.ts +0 -77
  89. package/dist/components/SequenceDiagramRenderer.d.ts.map +0 -1
  90. package/dist/components/SequenceDiagramRenderer.js +0 -604
  91. package/dist/components/SequenceDiagramRenderer.js.map +0 -1
  92. package/dist/components/WorkflowSequenceDiagram.d.ts +0 -63
  93. package/dist/components/WorkflowSequenceDiagram.d.ts.map +0 -1
  94. package/dist/components/WorkflowSequenceDiagram.js +0 -147
  95. package/dist/components/WorkflowSequenceDiagram.js.map +0 -1
  96. package/dist/components/dashboard/DashboardRenderer.d.ts +0 -10
  97. package/dist/components/dashboard/DashboardRenderer.d.ts.map +0 -1
  98. package/dist/components/dashboard/DashboardRenderer.js +0 -179
  99. package/dist/components/dashboard/DashboardRenderer.js.map +0 -1
  100. package/dist/components/dashboard/MetricPanel.d.ts +0 -10
  101. package/dist/components/dashboard/MetricPanel.d.ts.map +0 -1
  102. package/dist/components/dashboard/MetricPanel.js +0 -103
  103. package/dist/components/dashboard/MetricPanel.js.map +0 -1
  104. package/dist/components/dashboard/MockDataProvider.d.ts +0 -30
  105. package/dist/components/dashboard/MockDataProvider.d.ts.map +0 -1
  106. package/dist/components/dashboard/MockDataProvider.js +0 -270
  107. package/dist/components/dashboard/MockDataProvider.js.map +0 -1
  108. package/dist/components/dashboard/components/BarChart.d.ts +0 -10
  109. package/dist/components/dashboard/components/BarChart.d.ts.map +0 -1
  110. package/dist/components/dashboard/components/BarChart.js +0 -167
  111. package/dist/components/dashboard/components/BarChart.js.map +0 -1
  112. package/dist/components/dashboard/components/LineChart.d.ts +0 -10
  113. package/dist/components/dashboard/components/LineChart.d.ts.map +0 -1
  114. package/dist/components/dashboard/components/LineChart.js +0 -141
  115. package/dist/components/dashboard/components/LineChart.js.map +0 -1
  116. package/dist/components/dashboard/components/MetricCard.d.ts +0 -9
  117. package/dist/components/dashboard/components/MetricCard.d.ts.map +0 -1
  118. package/dist/components/dashboard/components/MetricCard.js +0 -163
  119. package/dist/components/dashboard/components/MetricCard.js.map +0 -1
  120. package/dist/components/dashboard/components/SourceLink.d.ts +0 -9
  121. package/dist/components/dashboard/components/SourceLink.d.ts.map +0 -1
  122. package/dist/components/dashboard/components/SourceLink.js +0 -39
  123. package/dist/components/dashboard/components/SourceLink.js.map +0 -1
  124. package/dist/components/dashboard/components/TimeRangeSelector.d.ts +0 -9
  125. package/dist/components/dashboard/components/TimeRangeSelector.d.ts.map +0 -1
  126. package/dist/components/dashboard/components/TimeRangeSelector.js +0 -167
  127. package/dist/components/dashboard/components/TimeRangeSelector.js.map +0 -1
  128. package/dist/components/dashboard/components/index.d.ts +0 -6
  129. package/dist/components/dashboard/components/index.d.ts.map +0 -1
  130. package/dist/components/dashboard/components/index.js +0 -6
  131. package/dist/components/dashboard/components/index.js.map +0 -1
  132. package/dist/components/dashboard/index.d.ts +0 -6
  133. package/dist/components/dashboard/index.d.ts.map +0 -1
  134. package/dist/components/dashboard/index.js +0 -8
  135. package/dist/components/dashboard/index.js.map +0 -1
  136. package/dist/components/dashboard/types.d.ts +0 -74
  137. package/dist/components/dashboard/types.d.ts.map +0 -1
  138. package/dist/components/dashboard/types.js +0 -8
  139. package/dist/components/dashboard/types.js.map +0 -1
  140. package/dist/components/state-view/PipelineView.d.ts +0 -14
  141. package/dist/components/state-view/PipelineView.d.ts.map +0 -1
  142. package/dist/components/state-view/PipelineView.js +0 -195
  143. package/dist/components/state-view/PipelineView.js.map +0 -1
  144. package/dist/components/state-view/index.d.ts +0 -14
  145. package/dist/components/state-view/index.d.ts.map +0 -1
  146. package/dist/components/state-view/index.js +0 -12
  147. package/dist/components/state-view/index.js.map +0 -1
  148. package/dist/components/state-view/types.d.ts +0 -188
  149. package/dist/components/state-view/types.d.ts.map +0 -1
  150. package/dist/components/state-view/types.js +0 -10
  151. package/dist/components/state-view/types.js.map +0 -1
  152. package/dist/components/state-view/useStateView.d.ts +0 -32
  153. package/dist/components/state-view/useStateView.d.ts.map +0 -1
  154. package/dist/components/state-view/useStateView.js +0 -129
  155. package/dist/components/state-view/useStateView.js.map +0 -1
  156. package/dist/contexts/GraphEditContext.d.ts +0 -20
  157. package/dist/contexts/GraphEditContext.d.ts.map +0 -1
  158. package/dist/contexts/GraphEditContext.js +0 -8
  159. package/dist/contexts/GraphEditContext.js.map +0 -1
  160. package/dist/contexts/TooltipPortalContext.d.ts +0 -8
  161. package/dist/contexts/TooltipPortalContext.d.ts.map +0 -1
  162. package/dist/contexts/TooltipPortalContext.js +0 -8
  163. package/dist/contexts/TooltipPortalContext.js.map +0 -1
  164. package/dist/edges/CustomEdge.d.ts +0 -24
  165. package/dist/edges/CustomEdge.d.ts.map +0 -1
  166. package/dist/edges/CustomEdge.js +0 -222
  167. package/dist/edges/CustomEdge.js.map +0 -1
  168. package/dist/edges/GenericEdge.d.ts +0 -18
  169. package/dist/edges/GenericEdge.d.ts.map +0 -1
  170. package/dist/edges/GenericEdge.js +0 -10
  171. package/dist/edges/GenericEdge.js.map +0 -1
  172. package/dist/graphify/kind.d.ts +0 -23
  173. package/dist/graphify/kind.d.ts.map +0 -1
  174. package/dist/graphify/kind.js +0 -77
  175. package/dist/graphify/kind.js.map +0 -1
  176. package/dist/hooks/usePathBasedEvents.d.ts +0 -42
  177. package/dist/hooks/usePathBasedEvents.d.ts.map +0 -1
  178. package/dist/hooks/usePathBasedEvents.js +0 -119
  179. package/dist/hooks/usePathBasedEvents.js.map +0 -1
  180. package/dist/hooks/useSequenceLayout.d.ts +0 -186
  181. package/dist/hooks/useSequenceLayout.d.ts.map +0 -1
  182. package/dist/hooks/useSequenceLayout.js +0 -327
  183. package/dist/hooks/useSequenceLayout.js.map +0 -1
  184. package/dist/hooks/useUndoRedo.d.ts +0 -80
  185. package/dist/hooks/useUndoRedo.d.ts.map +0 -1
  186. package/dist/hooks/useUndoRedo.js +0 -70
  187. package/dist/hooks/useUndoRedo.js.map +0 -1
  188. package/dist/nodes/CustomNode.d.ts +0 -28
  189. package/dist/nodes/CustomNode.d.ts.map +0 -1
  190. package/dist/nodes/CustomNode.js +0 -820
  191. package/dist/nodes/CustomNode.js.map +0 -1
  192. package/dist/nodes/GenericNode.d.ts +0 -20
  193. package/dist/nodes/GenericNode.d.ts.map +0 -1
  194. package/dist/nodes/GenericNode.js +0 -20
  195. package/dist/nodes/GenericNode.js.map +0 -1
  196. package/dist/nodes/otel/OtelBoundaryNode.d.ts +0 -55
  197. package/dist/nodes/otel/OtelBoundaryNode.d.ts.map +0 -1
  198. package/dist/nodes/otel/OtelBoundaryNode.js +0 -81
  199. package/dist/nodes/otel/OtelBoundaryNode.js.map +0 -1
  200. package/dist/nodes/otel/OtelEventNode.d.ts +0 -59
  201. package/dist/nodes/otel/OtelEventNode.d.ts.map +0 -1
  202. package/dist/nodes/otel/OtelEventNode.js +0 -82
  203. package/dist/nodes/otel/OtelEventNode.js.map +0 -1
  204. package/dist/nodes/otel/OtelResourceNode.d.ts +0 -53
  205. package/dist/nodes/otel/OtelResourceNode.d.ts.map +0 -1
  206. package/dist/nodes/otel/OtelResourceNode.js +0 -105
  207. package/dist/nodes/otel/OtelResourceNode.js.map +0 -1
  208. package/dist/nodes/otel/OtelScopeNode.d.ts +0 -53
  209. package/dist/nodes/otel/OtelScopeNode.d.ts.map +0 -1
  210. package/dist/nodes/otel/OtelScopeNode.js +0 -81
  211. package/dist/nodes/otel/OtelScopeNode.js.map +0 -1
  212. package/dist/nodes/otel/OtelSpanConventionNode.d.ts +0 -61
  213. package/dist/nodes/otel/OtelSpanConventionNode.d.ts.map +0 -1
  214. package/dist/nodes/otel/OtelSpanConventionNode.js +0 -131
  215. package/dist/nodes/otel/OtelSpanConventionNode.js.map +0 -1
  216. package/dist/nodes/otel/index.d.ts +0 -17
  217. package/dist/nodes/otel/index.d.ts.map +0 -1
  218. package/dist/nodes/otel/index.js +0 -13
  219. package/dist/nodes/otel/index.js.map +0 -1
  220. package/dist/nodes/otel/shared/NodeBadges.d.ts +0 -10
  221. package/dist/nodes/otel/shared/NodeBadges.d.ts.map +0 -1
  222. package/dist/nodes/otel/shared/NodeBadges.js +0 -178
  223. package/dist/nodes/otel/shared/NodeBadges.js.map +0 -1
  224. package/dist/nodes/otel/shared/NodeContent.d.ts +0 -10
  225. package/dist/nodes/otel/shared/NodeContent.d.ts.map +0 -1
  226. package/dist/nodes/otel/shared/NodeContent.js +0 -96
  227. package/dist/nodes/otel/shared/NodeContent.js.map +0 -1
  228. package/dist/nodes/otel/shared/index.d.ts +0 -8
  229. package/dist/nodes/otel/shared/index.d.ts.map +0 -1
  230. package/dist/nodes/otel/shared/index.js +0 -8
  231. package/dist/nodes/otel/shared/index.js.map +0 -1
  232. package/dist/nodes/otel/shared/types.d.ts +0 -129
  233. package/dist/nodes/otel/shared/types.d.ts.map +0 -1
  234. package/dist/nodes/otel/shared/types.js +0 -5
  235. package/dist/nodes/otel/shared/types.js.map +0 -1
  236. package/dist/nodes/otel/shared/useNodeBehavior.d.ts +0 -42
  237. package/dist/nodes/otel/shared/useNodeBehavior.d.ts.map +0 -1
  238. package/dist/nodes/otel/shared/useNodeBehavior.js +0 -61
  239. package/dist/nodes/otel/shared/useNodeBehavior.js.map +0 -1
  240. package/dist/pierre/PierreThroughlineCodeView.d.ts +0 -22
  241. package/dist/pierre/PierreThroughlineCodeView.d.ts.map +0 -1
  242. package/dist/pierre/PierreThroughlineCodeView.js +0 -206
  243. package/dist/pierre/PierreThroughlineCodeView.js.map +0 -1
  244. package/dist/subsystem/SubsystemCarousel.d.ts +0 -36
  245. package/dist/subsystem/SubsystemCarousel.d.ts.map +0 -1
  246. package/dist/subsystem/SubsystemCarousel.js +0 -163
  247. package/dist/subsystem/SubsystemCarousel.js.map +0 -1
  248. package/dist/utils/animationMapping.d.ts +0 -53
  249. package/dist/utils/animationMapping.d.ts.map +0 -1
  250. package/dist/utils/animationMapping.js +0 -126
  251. package/dist/utils/animationMapping.js.map +0 -1
  252. package/dist/utils/canvasBounds.d.ts +0 -50
  253. package/dist/utils/canvasBounds.d.ts.map +0 -1
  254. package/dist/utils/canvasBounds.js +0 -88
  255. package/dist/utils/canvasBounds.js.map +0 -1
  256. package/dist/utils/graphConverter.d.ts +0 -18
  257. package/dist/utils/graphConverter.d.ts.map +0 -1
  258. package/dist/utils/graphConverter.js +0 -114
  259. package/dist/utils/graphConverter.js.map +0 -1
  260. package/dist/utils/iconResolver.d.ts +0 -29
  261. package/dist/utils/iconResolver.d.ts.map +0 -1
  262. package/dist/utils/iconResolver.js +0 -30
  263. package/dist/utils/iconResolver.js.map +0 -1
  264. package/dist/utils/orientationUtils.d.ts +0 -19
  265. package/dist/utils/orientationUtils.d.ts.map +0 -1
  266. package/dist/utils/orientationUtils.js +0 -62
  267. package/dist/utils/orientationUtils.js.map +0 -1
@@ -0,0 +1,287 @@
1
+ import '@xyflow/react/dist/style.css';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
4
+ import { SubsystemComponentGraph } from '../../../subsystem/SubsystemComponentGraph';
5
+ import type { SubsystemComponent } from '../../../subsystem/model';
6
+ import { graphSpecFromEdges } from './fixtures';
7
+
8
+ const meta = {
9
+ title: 'Subsystem/ComponentGraph/Modules',
10
+ component: SubsystemComponentGraph,
11
+ parameters: { layout: 'fullscreen' },
12
+ tags: ['autodocs'],
13
+ decorators: [
14
+ (Story) => (
15
+ <ThemeProvider theme={defaultEditorTheme}>
16
+ <Story />
17
+ </ThemeProvider>
18
+ ),
19
+ ],
20
+ } satisfies Meta<typeof SubsystemComponentGraph>;
21
+
22
+ export default meta;
23
+ type Story = StoryObj<typeof meta>;
24
+
25
+ const PURL = 'pkg:github/principal-ai/agent-monitoring';
26
+
27
+ /**
28
+ * Module frames replace `construct: module`. Each export keeps its real
29
+ * construct; shared `module` (the source path) draws the file as a boundary.
30
+ */
31
+ const moduleComponents: SubsystemComponent[] = [
32
+ {
33
+ id: 'record',
34
+ name: 'CodexRolloutRecord',
35
+ construct: 'type_alias',
36
+ symbol: 'CodexRolloutRecord',
37
+ file: 'src/session/transcript.ts',
38
+ module: 'src/session/transcript.ts',
39
+ purl: PURL,
40
+ purpose: 'parsed rollout record shape',
41
+ layer: 1,
42
+ },
43
+ {
44
+ id: 'is-rollout',
45
+ name: 'isCodexRollout',
46
+ construct: 'function',
47
+ symbol: 'isCodexRollout',
48
+ file: 'src/session/transcript.ts',
49
+ module: 'src/session/transcript.ts',
50
+ purl: PURL,
51
+ purpose: 'type guard for rollout records',
52
+ layer: 1,
53
+ },
54
+ {
55
+ id: 'parse',
56
+ name: 'parseTranscript',
57
+ construct: 'function',
58
+ symbol: 'parseTranscript',
59
+ file: 'src/session/transcript.ts',
60
+ module: 'src/session/transcript.ts',
61
+ purl: PURL,
62
+ purpose: 'parses session transcript lines',
63
+ layer: 1,
64
+ },
65
+ {
66
+ id: 'tool-name',
67
+ name: 'extractToolName',
68
+ construct: 'function',
69
+ symbol: 'extractToolName',
70
+ file: 'src/session/paths.ts',
71
+ module: 'src/session/paths.ts',
72
+ purl: PURL,
73
+ purpose: 'pulls tool names from path-like strings',
74
+ layer: 2,
75
+ },
76
+ {
77
+ id: 'file-path',
78
+ name: 'extractFilePath',
79
+ construct: 'function',
80
+ symbol: 'extractFilePath',
81
+ file: 'src/session/paths.ts',
82
+ module: 'src/session/paths.ts',
83
+ purl: PURL,
84
+ purpose: 'pulls file paths from tool args',
85
+ layer: 2,
86
+ },
87
+ {
88
+ id: 'reader',
89
+ name: 'SessionReader',
90
+ construct: 'class',
91
+ symbol: 'SessionReader',
92
+ file: 'src/session/SessionReader.ts',
93
+ module: 'src/session/SessionReader.ts',
94
+ purl: PURL,
95
+ purpose: 'normalizes a session into universal events',
96
+ layer: 3,
97
+ },
98
+ {
99
+ id: 'normalize',
100
+ name: 'normalize',
101
+ construct: 'method',
102
+ symbol: 'SessionReader.normalize',
103
+ file: 'src/session/SessionReader.ts',
104
+ module: 'src/session/SessionReader.ts',
105
+ purl: PURL,
106
+ purpose: 'maps a session into universal events',
107
+ layer: 3,
108
+ },
109
+ {
110
+ id: 'registry',
111
+ name: 'registerAgent',
112
+ construct: 'function',
113
+ symbol: 'registerAgent',
114
+ file: 'src/supported-agents.ts',
115
+ // Singleton module — no frame (same rule as process: need 2+ members).
116
+ module: 'src/supported-agents.ts',
117
+ purl: PURL,
118
+ purpose: 'registers a supported agent (singleton file — no module frame)',
119
+ layer: 4,
120
+ },
121
+ ];
122
+
123
+ const moduleEdges = graphSpecFromEdges([
124
+ ['parse', 'record', 'references'],
125
+ ['is-rollout', 'record', 'references'],
126
+ ['reader', 'normalize', 'method'],
127
+ ['normalize', 'parse', 'calls'],
128
+ ['normalize', 'tool-name', 'calls'],
129
+ ['normalize', 'file-path', 'calls'],
130
+ ['reader', 'registry', 'registers-into'],
131
+ ]);
132
+
133
+ export const ModuleBoundaries: Story = {
134
+ render: () => (
135
+ <div style={{ width: '100%', height: '100vh' }}>
136
+ <SubsystemComponentGraph
137
+ title="Module boundaries"
138
+ description="Concrete exports keep their real construct. Shared `module` (the source path) draws the file as a dashed frame — not `construct: module`. Singleton modules (registerAgent) stay unframed."
139
+ components={moduleComponents}
140
+ relations={moduleEdges.relations}
141
+ walkthroughs={moduleEdges.walkthroughs}
142
+ />
143
+ </div>
144
+ ),
145
+ };
146
+
147
+ /** Process → module → export nesting (host / renderer). */
148
+ const nestedComponents: SubsystemComponent[] = [
149
+ {
150
+ id: 'boot',
151
+ name: 'boot',
152
+ construct: 'function',
153
+ symbol: 'boot',
154
+ role: 'entry',
155
+ file: 'src/host/main.ts',
156
+ module: 'src/host/main.ts',
157
+ process: 'principal-studio/host',
158
+ purl: 'pkg:github/principal-ai/principal-studio',
159
+ purpose: 'Boots the host process',
160
+ layer: 1,
161
+ },
162
+ {
163
+ id: 'create-host',
164
+ name: 'createHost',
165
+ construct: 'function',
166
+ symbol: 'createHost',
167
+ file: 'src/host/main.ts',
168
+ module: 'src/host/main.ts',
169
+ process: 'principal-studio/host',
170
+ purl: 'pkg:github/principal-ai/principal-studio',
171
+ purpose: 'Constructs the host runtime',
172
+ layer: 1,
173
+ },
174
+ {
175
+ id: 'session-store',
176
+ name: 'SessionStore',
177
+ construct: 'store',
178
+ symbol: 'SessionStore',
179
+ file: 'src/host/store.ts',
180
+ module: 'src/host/store.ts',
181
+ process: 'principal-studio/host',
182
+ purl: 'pkg:github/principal-ai/principal-studio',
183
+ purpose: 'Retained host session state',
184
+ layer: 2,
185
+ },
186
+ {
187
+ id: 'write-session',
188
+ name: 'writeSession',
189
+ construct: 'function',
190
+ symbol: 'writeSession',
191
+ file: 'src/host/store.ts',
192
+ module: 'src/host/store.ts',
193
+ process: 'principal-studio/host',
194
+ purl: 'pkg:github/principal-ai/principal-studio',
195
+ purpose: 'Mutates SessionStore',
196
+ layer: 2,
197
+ },
198
+ {
199
+ id: 'bridge',
200
+ name: 'bridge',
201
+ construct: 'function',
202
+ symbol: 'bridge',
203
+ role: 'entry',
204
+ file: 'src/renderer/bridge.ts',
205
+ module: 'src/renderer/bridge.ts',
206
+ process: 'principal-studio/renderer',
207
+ purl: 'pkg:github/principal-ai/principal-studio',
208
+ purpose: 'Renderer IPC entry',
209
+ layer: 3,
210
+ },
211
+ {
212
+ id: 'post-to-host',
213
+ name: 'postToHost',
214
+ construct: 'function',
215
+ symbol: 'postToHost',
216
+ file: 'src/renderer/bridge.ts',
217
+ module: 'src/renderer/bridge.ts',
218
+ process: 'principal-studio/renderer',
219
+ purl: 'pkg:github/principal-ai/principal-studio',
220
+ purpose: 'Sends a message to the host',
221
+ layer: 3,
222
+ },
223
+ {
224
+ id: 'trail-view',
225
+ name: 'TrailView',
226
+ construct: 'function',
227
+ symbol: 'TrailView',
228
+ framework: 'react',
229
+ stereotype: 'component',
230
+ file: 'src/renderer/view.tsx',
231
+ module: 'src/renderer/view.tsx',
232
+ process: 'principal-studio/renderer',
233
+ purl: 'pkg:github/principal-ai/principal-studio',
234
+ purpose: 'Renders the trail',
235
+ layer: 4,
236
+ },
237
+ {
238
+ id: 'use-trail',
239
+ name: 'useTrail',
240
+ construct: 'function',
241
+ symbol: 'useTrail',
242
+ framework: 'react',
243
+ stereotype: 'hook',
244
+ file: 'src/renderer/view.tsx',
245
+ module: 'src/renderer/view.tsx',
246
+ process: 'principal-studio/renderer',
247
+ purl: 'pkg:github/principal-ai/principal-studio',
248
+ purpose: 'Subscribes the view to trail updates',
249
+ layer: 4,
250
+ },
251
+ {
252
+ id: 'telemetry',
253
+ name: 'telemetry',
254
+ construct: 'external',
255
+ role: 'service',
256
+ file: '',
257
+ purl: 'external',
258
+ purpose: 'External sink — outside every frame',
259
+ layer: 5,
260
+ },
261
+ ];
262
+
263
+ const nestedEdges = graphSpecFromEdges([
264
+ ['boot', 'write-session', 'imports'],
265
+ ['trail-view', 'bridge', 'imports'],
266
+ ['trail-view', 'use-trail', 'references'],
267
+ ['boot', 'create-host', 'calls'],
268
+ ['create-host', 'write-session', 'calls'],
269
+ ['write-session', 'session-store', 'writes'],
270
+ ['bridge', 'boot', 'calls'],
271
+ ['trail-view', 'post-to-host', 'calls'],
272
+ ['boot', 'telemetry', 'uses'],
273
+ ]);
274
+
275
+ export const ProcessAndModuleNesting: Story = {
276
+ render: () => (
277
+ <div style={{ width: '100%', height: '100vh' }}>
278
+ <SubsystemComponentGraph
279
+ title="Process × module nesting"
280
+ description="process frames wrap module frames wrap exports. Leaves parent to module:; module groups parent to process: when every member shares that process."
281
+ components={nestedComponents}
282
+ relations={nestedEdges.relations}
283
+ walkthroughs={nestedEdges.walkthroughs}
284
+ />
285
+ </div>
286
+ ),
287
+ };
@@ -28,7 +28,7 @@ const processComponents = [
28
28
  ['main', 'main', 'function', 'src/host/main.ts', 'pkg:github/principal-ai/principal-studio', 'boots the host process', 'main'],
29
29
  ['store', 'SessionStore', 'store', 'src/host/store.ts', 'pkg:github/principal-ai/principal-studio', 'retained host state', 'SessionStore'],
30
30
  ['view', 'TrailView', 'function', 'src/renderer/view.tsx', 'pkg:github/principal-ai/principal-studio', 'renders the trail', 'TrailView'],
31
- ['bridge', 'bridge', 'module', 'src/renderer/bridge.ts', 'pkg:github/principal-ai/principal-studio', 'IPC bridge to the host', 'bridge'],
31
+ ['bridge', 'bridge', 'function', 'src/renderer/bridge.ts', 'pkg:github/principal-ai/principal-studio', 'IPC bridge to the host', 'bridge'],
32
32
  ]),
33
33
  {
34
34
  id: 'svc',
@@ -84,7 +84,7 @@ const mermaidComponents: SubsystemComponent[] = [
84
84
  {
85
85
  id: 'helpers',
86
86
  name: 'beautifulMermaid',
87
- construct: 'module',
87
+ construct: 'function',
88
88
  file: 'industryMarkdown/utils/beautifulMermaid.ts',
89
89
  purl: mermaidPurl,
90
90
  purpose: 'engine detection, theme\u2192options mapping, SVG post-processing',
@@ -130,11 +130,11 @@ const coreLibPurl = 'pkg:github/principal-ai/principal-view-core-library';
130
130
  const graphifyPurl = 'pkg:github/Graphify-Labs/graphify';
131
131
 
132
132
  const multiRepoComponents = components([
133
- ['resolver', 'resolve.ts', 'module', 'packages/subsystems-react/src/graphify/resolve.ts', coreLibPurl, 'consumer-side resolution mirroring graphify rewire tiers', 'createGraphifyTypeResolver'],
134
- ['reftypes', 'consolidated.ts', 'module', 'packages/subsystems-react/src/graphify/consolidated.ts', coreLibPurl, 'drill-down payload types carrying ref.nodeId', 'GraphifyParamInfo'],
135
- ['detail', 'ComponentDeclaration.tsx', 'module', 'packages/subsystems-react/src/subsystem/ComponentDeclaration.tsx', coreLibPurl, 'declaration panel rendering the selected component as code, with clickable type tokens', 'ComponentDeclaration'],
136
- ['engine', 'engine.py', 'module', 'graphify/extractors/engine.py', graphifyPurl, 'tree-sitter walk emitting references[parameter_type] edges + sourceless stubs', 'ensure_named_node'],
137
- ['rewire', 'extract.py', 'module', 'graphify/extract.py', graphifyPurl, 'corpus pass folding unique-label stubs onto definitions', '_rewire_unique_stub_nodes'],
133
+ ['resolver', 'resolve.ts', 'function', 'packages/subsystems-react/src/graphify/resolve.ts', coreLibPurl, 'consumer-side resolution mirroring graphify rewire tiers', 'createGraphifyTypeResolver'],
134
+ ['reftypes', 'consolidated.ts', 'function', 'packages/subsystems-react/src/graphify/consolidated.ts', coreLibPurl, 'drill-down payload types carrying ref.nodeId', 'GraphifyParamInfo'],
135
+ ['detail', 'ComponentDeclaration.tsx', 'function', 'packages/subsystems-react/src/subsystem/ComponentDeclaration.tsx', coreLibPurl, 'declaration panel rendering the selected component as code, with clickable type tokens', 'ComponentDeclaration'],
136
+ ['engine', 'engine.py', 'function', 'graphify/extractors/engine.py', graphifyPurl, 'tree-sitter walk emitting references[parameter_type] edges + sourceless stubs', 'ensure_named_node'],
137
+ ['rewire', 'extract.py', 'function', 'graphify/extract.py', graphifyPurl, 'corpus pass folding unique-label stubs onto definitions', '_rewire_unique_stub_nodes'],
138
138
  ]);
139
139
 
140
140
  const multiRepoEdges = graphSpecFromEdges([
@@ -29,9 +29,6 @@ export function components(
29
29
 
30
30
  const RELATION_TYPES = new Set<string>([
31
31
  'imports',
32
- 'imports_from',
33
- 're_exports',
34
- 'defines',
35
32
  'extends',
36
33
  'inherits',
37
34
  'implements',
@@ -39,8 +39,6 @@ export function generateDeclarationString(component: SubsystemComponent): string
39
39
  case 'type_alias':
40
40
  case 'enum':
41
41
  return generateType(name, component.construct, declaration);
42
- case 'module':
43
- return generateModule(declaration);
44
42
  case 'store':
45
43
  return generateStore(name, declaration);
46
44
  case 'external':
@@ -175,23 +173,6 @@ function generateType(
175
173
  }
176
174
  }
177
175
 
178
- function generateModule(declaration?: GraphifyComponentDetail): string {
179
- const mod = declaration?.kind === 'module' ? declaration : undefined;
180
- if (!mod) return 'module {}';
181
-
182
- const parts: string[] = [];
183
-
184
- for (const imp of mod.imports ?? []) {
185
- parts.push(`import '${imp.name}';`);
186
- }
187
-
188
- if ((mod.exports ?? []).length > 0) {
189
- parts.push(`export { ${mod.exports!.join(', ')} };`);
190
- }
191
-
192
- return parts.join('\n') || `module {}`;
193
- }
194
-
195
176
  /**
196
177
  * A store renders as its retained state — ambient `declare const` lines for
197
178
  * the state members, never a class/method stub. The node's name labels the
@@ -4,7 +4,9 @@ import {
4
4
  convertSubsystemToEdges,
5
5
  convertSubsystemToGroups,
6
6
  getSubsystemRegions,
7
+ getSubsystemModuleRegions,
7
8
  processGroupNodeId,
9
+ moduleGroupNodeId,
8
10
  buildSubsystemGraph,
9
11
  deriveNameFromSymbol,
10
12
  constructBadgeLabel,
@@ -94,10 +96,10 @@ describe('subsystem graph model', () => {
94
96
  });
95
97
 
96
98
  test('deriveNameFromSymbol is consistent per kind', () => {
97
- // brace-bodied constructs wear {}; classes render bare; module uses the symbol as-is.
99
+ // brace-bodied constructs wear {}; classes render bare.
98
100
  expect(deriveNameFromSymbol('SessionReader', 'class')).toBe('SessionReader');
99
101
  expect(deriveNameFromSymbol('SessionRecord', 'type_alias')).toBe('SessionRecord {}');
100
- expect(deriveNameFromSymbol('transcript', 'module')).toBe('transcript');
102
+ expect(deriveNameFromSymbol('transcript', 'function')).toBe('transcript()');
101
103
  // falls back to existing name when no symbol (class stays bare).
102
104
  expect(deriveNameFromSymbol(undefined, 'class', 'SessionReader')).toBe('SessionReader');
103
105
  expect(deriveNameFromSymbol('', 'external', 'principal-studio-host')).toBe('principal-studio-host');
@@ -187,13 +189,13 @@ describe('subsystem graph model', () => {
187
189
  expect(rightBadgeLabel({ role: 'service', proposed: true })).toBe('proposed');
188
190
  });
189
191
 
190
- test('deriveNameFromSymbol falls back to file basename for modules', () => {
191
- expect(deriveNameFromSymbol(undefined, 'module', undefined, 'transcript.ts')).toBe('transcript');
192
- expect(deriveNameFromSymbol(undefined, 'module', undefined, 'src/event-processors/index.ts')).toBe('index');
193
- // Symbol wins over file basename.
194
- expect(deriveNameFromSymbol('CodexRolloutRecord', 'module', undefined, 'transcript.ts')).toBe('CodexRolloutRecord');
195
- // File basename wins over a supplied name for modules (derivation precedence).
196
- expect(deriveNameFromSymbol(undefined, 'module', 'MyModule', 'x.ts')).toBe('x');
192
+ test('deriveNameFromSymbol falls back to existing name when no symbol', () => {
193
+ expect(deriveNameFromSymbol(undefined, 'class', undefined, 'transcript.ts')).toBe('untitled');
194
+ expect(deriveNameFromSymbol(undefined, 'function', 'MyFn', 'x.ts')).toBe('MyFn()');
195
+ // Symbol wins over a supplied name.
196
+ expect(deriveNameFromSymbol('CodexRolloutRecord', 'function', undefined, 'transcript.ts')).toBe(
197
+ 'CodexRolloutRecord()',
198
+ );
197
199
  });
198
200
 
199
201
  test('formatPurl renders the human identity', () => {
@@ -216,9 +218,49 @@ describe('subsystem graph model', () => {
216
218
  ],
217
219
  });
218
220
  expect(regions.map((r) => r.key)).toEqual(['app/host', 'app/renderer']);
221
+ expect(regions.every((r) => r.kind === 'process')).toBe(true);
219
222
  expect(regions[0]!.memberIds).toEqual(['a', 'b']);
220
223
  });
221
224
 
225
+ test('getSubsystemModuleRegions groups by module, skipping module-less nodes', () => {
226
+ const regions = getSubsystemModuleRegions({
227
+ components: [
228
+ { id: 'a', name: 'a', construct: 'function', file: 'transcript.ts', purl: 'pkg:github/acme/app', module: 'src/session/transcript.ts' },
229
+ { id: 'b', name: 'b', construct: 'type_alias', file: 'transcript.ts', purl: 'pkg:github/acme/app', module: 'src/session/transcript.ts' },
230
+ { id: 'c', name: 'c', construct: 'function', file: 'paths.ts', purl: 'pkg:github/acme/app', module: 'src/session/paths.ts' },
231
+ { id: 'd', name: 'd', construct: 'function', file: 'other.ts', purl: 'pkg:github/acme/app' },
232
+ ],
233
+ });
234
+ expect(regions.map((r) => r.key)).toEqual([
235
+ 'src/session/transcript.ts',
236
+ 'src/session/paths.ts',
237
+ ]);
238
+ expect(regions.every((r) => r.kind === 'module')).toBe(true);
239
+ expect(regions[0]!.memberIds).toEqual(['a', 'b']);
240
+ });
241
+
242
+ test('convertSubsystemToNodes prefers module parentId over process', () => {
243
+ const nodes = convertSubsystemToNodes({
244
+ components: [
245
+ {
246
+ id: 'a',
247
+ name: 'a',
248
+ construct: 'function',
249
+ file: 'a.ts',
250
+ purl: 'pkg:github/acme/app',
251
+ process: 'app/host',
252
+ module: 'src/a.ts',
253
+ },
254
+ { id: 'd', name: 'd', construct: 'function', file: 'd.ts', purl: 'pkg:github/acme/app' },
255
+ ],
256
+ relations: [],
257
+ });
258
+ expect((nodes.find((n) => n.id === 'a') as { parentId?: string }).parentId).toBe(
259
+ moduleGroupNodeId('src/a.ts'),
260
+ );
261
+ expect((nodes.find((n) => n.id === 'd') as { parentId?: string }).parentId).toBeUndefined();
262
+ });
263
+
222
264
  test('convertSubsystemToNodes stamps parentId for process members only', () => {
223
265
  const nodes = convertSubsystemToNodes({
224
266
  components: [
@@ -245,6 +287,103 @@ describe('subsystem graph model', () => {
245
287
  expect(groups[0]!.type).toBe('subsystem-group');
246
288
  });
247
289
 
290
+ test('convertSubsystemToGroups nests module frames under a shared process', () => {
291
+ const groups = convertSubsystemToGroups({
292
+ components: [
293
+ {
294
+ id: 'a',
295
+ name: 'a',
296
+ construct: 'function',
297
+ file: 'a.ts',
298
+ purl: 'pkg:github/acme/app',
299
+ process: 'app/host',
300
+ module: 'src/a.ts',
301
+ },
302
+ {
303
+ id: 'b',
304
+ name: 'b',
305
+ construct: 'function',
306
+ file: 'a.ts',
307
+ purl: 'pkg:github/acme/app',
308
+ process: 'app/host',
309
+ module: 'src/a.ts',
310
+ },
311
+ ],
312
+ });
313
+ expect(groups.map((g) => g.id).sort()).toEqual(
314
+ [moduleGroupNodeId('src/a.ts'), processGroupNodeId('app/host')].sort(),
315
+ );
316
+ const mod = groups.find((g) => g.id === moduleGroupNodeId('src/a.ts'));
317
+ expect((mod as { parentId?: string }).parentId).toBe(processGroupNodeId('app/host'));
318
+ const proc = groups.find((g) => g.id === processGroupNodeId('app/host'));
319
+ expect((proc as { parentId?: string }).parentId).toBeUndefined();
320
+ });
321
+
322
+ test('buildSubsystemGraph nests module frames inside process frames', async () => {
323
+ const { nodes, regions } = await buildSubsystemGraph({
324
+ components: [
325
+ {
326
+ id: 'boot',
327
+ name: 'boot',
328
+ construct: 'function',
329
+ file: 'main.ts',
330
+ purl: 'pkg:github/acme/app',
331
+ process: 'app/host',
332
+ module: 'src/main.ts',
333
+ symbol: 'boot',
334
+ },
335
+ {
336
+ id: 'create',
337
+ name: 'createHost',
338
+ construct: 'function',
339
+ file: 'main.ts',
340
+ purl: 'pkg:github/acme/app',
341
+ process: 'app/host',
342
+ module: 'src/main.ts',
343
+ symbol: 'createHost',
344
+ },
345
+ {
346
+ id: 'write',
347
+ name: 'writeSession',
348
+ construct: 'function',
349
+ file: 'store.ts',
350
+ purl: 'pkg:github/acme/app',
351
+ process: 'app/host',
352
+ module: 'src/store.ts',
353
+ symbol: 'writeSession',
354
+ },
355
+ {
356
+ id: 'store',
357
+ name: 'SessionStore',
358
+ construct: 'store',
359
+ file: 'store.ts',
360
+ purl: 'pkg:github/acme/app',
361
+ process: 'app/host',
362
+ module: 'src/store.ts',
363
+ symbol: 'SessionStore',
364
+ },
365
+ ],
366
+ relations: [],
367
+ });
368
+ expect(regions.map((r) => r.key).sort()).toEqual(
369
+ ['app/host', 'src/main.ts', 'src/store.ts'].sort(),
370
+ );
371
+ const processNode = nodes.find((n) => n.id === processGroupNodeId('app/host'));
372
+ const mainMod = nodes.find((n) => n.id === moduleGroupNodeId('src/main.ts'));
373
+ const storeMod = nodes.find((n) => n.id === moduleGroupNodeId('src/store.ts'));
374
+ expect(processNode).toBeDefined();
375
+ expect(mainMod).toBeDefined();
376
+ expect(storeMod).toBeDefined();
377
+ expect((mainMod as { parentId?: string }).parentId).toBe(processGroupNodeId('app/host'));
378
+ expect((storeMod as { parentId?: string }).parentId).toBe(processGroupNodeId('app/host'));
379
+ expect((nodes.find((n) => n.id === 'boot') as { parentId?: string }).parentId).toBe(
380
+ moduleGroupNodeId('src/main.ts'),
381
+ );
382
+ expect((nodes.find((n) => n.id === 'store') as { parentId?: string }).parentId).toBe(
383
+ moduleGroupNodeId('src/store.ts'),
384
+ );
385
+ });
386
+
248
387
  test('buildSubsystemGraph drops singleton process frames (no parentId, no group)', async () => {
249
388
  const { nodes, regions } = await buildSubsystemGraph({
250
389
  components: [
@@ -264,6 +403,48 @@ describe('subsystem graph model', () => {
264
403
  expect(nodes.find((n) => n.id === processGroupNodeId('app/lonely'))).toBeUndefined();
265
404
  });
266
405
 
406
+ test('buildSubsystemGraph frames multi-member modules', async () => {
407
+ const { nodes, regions } = await buildSubsystemGraph({
408
+ components: [
409
+ {
410
+ id: 'rec',
411
+ name: 'CodexRolloutRecord',
412
+ construct: 'type_alias',
413
+ file: 'transcript.ts',
414
+ purl: 'pkg:github/acme/app',
415
+ module: 'src/session/transcript.ts',
416
+ symbol: 'CodexRolloutRecord',
417
+ },
418
+ {
419
+ id: 'parse',
420
+ name: 'parseTranscript',
421
+ construct: 'function',
422
+ file: 'transcript.ts',
423
+ purl: 'pkg:github/acme/app',
424
+ module: 'src/session/transcript.ts',
425
+ symbol: 'parseTranscript',
426
+ },
427
+ {
428
+ id: 'solo',
429
+ name: 'lonely',
430
+ construct: 'function',
431
+ file: 'solo.ts',
432
+ purl: 'pkg:github/acme/app',
433
+ module: 'src/solo.ts',
434
+ symbol: 'lonely',
435
+ },
436
+ ],
437
+ relations: [],
438
+ });
439
+ expect(regions.map((r) => r.key)).toEqual(['src/session/transcript.ts']);
440
+ expect(regions[0]!.kind).toBe('module');
441
+ expect((nodes.find((n) => n.id === 'rec') as { parentId?: string }).parentId).toBe(
442
+ moduleGroupNodeId('src/session/transcript.ts'),
443
+ );
444
+ expect((nodes.find((n) => n.id === 'solo') as { parentId?: string }).parentId).toBeUndefined();
445
+ expect(nodes.find((n) => n.id === moduleGroupNodeId('src/session/transcript.ts'))).toBeDefined();
446
+ });
447
+
267
448
  test('subsystemGraphLayoutKey ignores declarationRef-only changes', () => {
268
449
  const base = doc;
269
450
  const withRef = {