@principal-ai/subsystems-react 0.42.0 → 0.43.1

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 (81) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/stories/Subsystem/C4Graph/c4Fixture.js +1 -1
  6. package/dist/stories/Subsystem/C4Graph/c4Fixture.js.map +1 -1
  7. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts +6 -9
  8. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts.map +1 -1
  9. package/dist/stories/Subsystem/ComponentGraph/fixtures.js +15 -50
  10. package/dist/stories/Subsystem/ComponentGraph/fixtures.js.map +1 -1
  11. package/dist/subsystem/C4Graph.d.ts +2 -3
  12. package/dist/subsystem/C4Graph.d.ts.map +1 -1
  13. package/dist/subsystem/C4Graph.js +2 -3
  14. package/dist/subsystem/C4Graph.js.map +1 -1
  15. package/dist/subsystem/IssueList.d.ts +5 -5
  16. package/dist/subsystem/IssueList.d.ts.map +1 -1
  17. package/dist/subsystem/IssueList.js +9 -18
  18. package/dist/subsystem/IssueList.js.map +1 -1
  19. package/dist/subsystem/SubsystemComponentGraph.d.ts +16 -12
  20. package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
  21. package/dist/subsystem/SubsystemComponentGraph.js +99 -113
  22. package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
  23. package/dist/subsystem/SubsystemFileTree.d.ts +5 -5
  24. package/dist/subsystem/SubsystemFileTree.d.ts.map +1 -1
  25. package/dist/subsystem/SubsystemFileTree.js +13 -49
  26. package/dist/subsystem/SubsystemFileTree.js.map +1 -1
  27. package/dist/subsystem/model.d.ts +67 -53
  28. package/dist/subsystem/model.d.ts.map +1 -1
  29. package/dist/subsystem/model.js +305 -55
  30. package/dist/subsystem/model.js.map +1 -1
  31. package/dist/subsystem/nodes.d.ts.map +1 -1
  32. package/dist/subsystem/nodes.js +11 -4
  33. package/dist/subsystem/nodes.js.map +1 -1
  34. package/dist/subsystem/toC4.d.ts +4 -4
  35. package/dist/subsystem/toC4.d.ts.map +1 -1
  36. package/dist/subsystem/toC4.js +3 -7
  37. package/dist/subsystem/toC4.js.map +1 -1
  38. package/dist/utils/elkLayout.d.ts.map +1 -1
  39. package/dist/utils/elkLayout.js +7 -0
  40. package/dist/utils/elkLayout.js.map +1 -1
  41. package/package.json +3 -3
  42. package/src/index.ts +0 -4
  43. package/src/stories/Subsystem/AgentsPanel.stories.tsx +3 -5
  44. package/src/stories/Subsystem/C4Graph/C4Container.stories.tsx +1 -4
  45. package/src/stories/Subsystem/C4Graph/c4Fixture.ts +1 -1
  46. package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +2 -4
  47. package/src/stories/Subsystem/ComponentGraph/Basics.stories.tsx +8 -8
  48. package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +19 -19
  49. package/src/stories/Subsystem/ComponentGraph/Constructs.stories.tsx +0 -1
  50. package/src/stories/Subsystem/ComponentGraph/CustomEntities.stories.tsx +3 -3
  51. package/src/stories/Subsystem/ComponentGraph/DetailPanel.stories.tsx +0 -2
  52. package/src/stories/Subsystem/ComponentGraph/Diagnostics.stories.tsx +2 -6
  53. package/src/stories/Subsystem/ComponentGraph/EdgeViews.stories.tsx +21 -21
  54. package/src/stories/Subsystem/ComponentGraph/Flows.stories.tsx +0 -3
  55. package/src/stories/Subsystem/ComponentGraph/FrameworkStereotype.stories.tsx +30 -32
  56. package/src/stories/Subsystem/ComponentGraph/GraphTitle.stories.tsx +4 -4
  57. package/src/stories/Subsystem/ComponentGraph/IssueOverlay.stories.tsx +1 -26
  58. package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +3 -25
  59. package/src/stories/Subsystem/ComponentGraph/ModuleBadges.stories.tsx +7 -8
  60. package/src/stories/Subsystem/ComponentGraph/ModulePathNesting.stories.tsx +116 -0
  61. package/src/stories/Subsystem/ComponentGraph/Modules.stories.tsx +9 -11
  62. package/src/stories/Subsystem/ComponentGraph/Packages.stories.tsx +3 -6
  63. package/src/stories/Subsystem/ComponentGraph/Processes.stories.tsx +3 -3
  64. package/src/stories/Subsystem/ComponentGraph/Proposed.stories.tsx +8 -6
  65. package/src/stories/Subsystem/ComponentGraph/ProposedWalkthroughs.stories.tsx +0 -1
  66. package/src/stories/Subsystem/ComponentGraph/Reorder.stories.tsx +0 -1
  67. package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +26 -28
  68. package/src/stories/Subsystem/ComponentGraph/WalkthroughAutoplay.stories.tsx +0 -1
  69. package/src/stories/Subsystem/ComponentGraph/WorkspacePackageFrames.stories.tsx +2 -3
  70. package/src/stories/Subsystem/ComponentGraph/fixtures.ts +18 -58
  71. package/src/stories/Subsystem/EgoGraph/EgoGraph.stories.tsx +0 -2
  72. package/src/subsystem/C4Graph.tsx +2 -3
  73. package/src/subsystem/IssueList.tsx +12 -22
  74. package/src/subsystem/SubsystemComponentGraph.tsx +117 -135
  75. package/src/subsystem/SubsystemFileTree.tsx +17 -50
  76. package/src/subsystem/model.test.ts +155 -24
  77. package/src/subsystem/model.ts +352 -108
  78. package/src/subsystem/nodes.tsx +13 -3
  79. package/src/subsystem/toC4.test.ts +5 -12
  80. package/src/subsystem/toC4.ts +5 -9
  81. package/src/utils/elkLayout.ts +10 -0
@@ -33,6 +33,8 @@ import {
33
33
  moduleBadgeHoverLabel,
34
34
  moduleBadgeWidth,
35
35
  packageColor,
36
+ FOLDER_FRAME_COLOR,
37
+ isFolderFrame,
36
38
  type SubsystemGraphNodeData,
37
39
  type SubsystemGroupNodeData,
38
40
  type SubsystemGraphEdge,
@@ -445,8 +447,14 @@ export function SubsystemGroupNode(props: NodeProps<Node<SubsystemGroupNodeData,
445
447
  selected?: boolean;
446
448
  };
447
449
  const region = data.region;
448
- // Explicit host override wins over the derived (hash-based) frame color.
449
- const color = data.color ?? packageColor(region?.key ?? 'process');
450
+ // Explicit host override wins over the derived frame color. Folder frames
451
+ // (directory, or a module whose key names a folder) share one neutral hue;
452
+ // everything else hashes per key.
453
+ const color =
454
+ data.color ??
455
+ (isFolderFrame(region ?? undefined)
456
+ ? FOLDER_FRAME_COLOR
457
+ : packageColor(region?.key ?? 'process'));
450
458
  const dimmed = data.dimmed === true;
451
459
  const hidden = (data as { hidden?: boolean }).hidden === true;
452
460
  // Label is the region identity alone (path / process key / owner/name).
@@ -454,7 +462,9 @@ export function SubsystemGroupNode(props: NodeProps<Node<SubsystemGroupNodeData,
454
462
  // — don't prefix `module ·` / `package ·` or the path reads twice.
455
463
  const label = region?.label ?? '';
456
464
  const [expandedLabel, setExpandedLabel] = useState<string | null>(null);
457
- const isModule = region?.kind === 'module';
465
+ // Directory frames (path-derived nesting) render like modules — dashed,
466
+ // collapsible path badge.
467
+ const isModule = region?.kind === 'module' || region?.kind === 'directory';
458
468
  const isProcess = region?.kind === 'process';
459
469
  const expanded = isModule && expandedLabel === label;
460
470
  const availableBadgeWidth = Math.max(0, (width ?? 400) - MODULE_BADGE_INSET * 2 - 4);
@@ -18,17 +18,12 @@ const doc: SubsystemModelDocument = {
18
18
  { alias: 'x', name: 'Gist API', construct: 'external', file: '', purl: 'external:api.github.com/gists' },
19
19
  { alias: 'agent', name: 'Maintenance agent', construct: 'custom_entity', file: '', purl: 'external' },
20
20
  ],
21
- relations: [
22
- { id: 'r1', from: 'a', to: 'b', relationType: 'method' }, // intra p1
23
- { id: 'r2', from: 'a', to: 'c', relationType: 'method' },
24
- { id: 'r3', from: 'b', to: 'c', relationType: 'method' },
25
- { id: 'r4', from: 'a', to: 'x', relationType: 'method' },
26
- ],
27
21
  walkthroughs: [
28
22
  {
29
23
  id: 'w1',
30
24
  title: 'flow',
31
25
  steps: [
26
+ { from: 'a', to: 'b', mechanism: 'calls', file: 'src/a.ts', line: 1, purl: `${REPO}#src/a.ts`, symbol: 'Alpha' },
32
27
  { from: 'b', to: 'c', mechanism: 'calls', file: 'src/b.ts', line: 1, purl: `${REPO}#src/b.ts`, symbol: 'Beta' },
33
28
  { from: 'a', to: 'c', mechanism: 'calls', file: 'src/a.ts', line: 2, purl: `${REPO}#src/a.ts`, symbol: 'Alpha' },
34
29
  { from: 'a', to: 'agent', mechanism: 'calls', file: 'src/a.ts', line: 3, purl: `${REPO}#src/a.ts`, symbol: 'Alpha' },
@@ -77,18 +72,16 @@ describe('container view', () => {
77
72
  expect(model.groups[0]!.memberIds.sort()).toEqual(['container:p1', 'container:p2']);
78
73
  });
79
74
 
80
- test('edges roll up and intra-container edges drop', () => {
75
+ test('flow edges roll up to containers; only flow edges exist', () => {
81
76
  const byId = Object.fromEntries(model.edges.map((e) => [e.id, e]));
82
77
  // a->b is intra-p1 — dropped.
83
78
  expect(model.edges.some((e) => e.source === e.target)).toBe(false);
84
- const rel = byId['relationship:container:p1\u0000container:p2']!;
85
- expect(rel.kind).toBe('relationship');
86
- expect(rel.count).toBe(2); // r2 + r3
87
79
  const flow = byId['flow:container:p1\u0000container:p2']!;
80
+ expect(flow.kind).toBe('flow');
88
81
  expect(flow.count).toBe(2); // a->c + b->c
89
- expect(byId['relationship:container:p1\u0000external:external:api.github.com/gists']).toBeDefined();
90
82
  expect(byId['flow:container:p1\u0000actor:agent']).toBeDefined();
91
- expect(model.edges).toHaveLength(4);
83
+ expect(model.edges.every((e) => e.kind === 'flow')).toBe(true);
84
+ expect(model.edges).toHaveLength(2);
92
85
  });
93
86
  });
94
87
 
@@ -2,8 +2,8 @@
2
2
  * toC4 — project a subsystem-model (or a composition of them) onto C4 levels.
3
3
  *
4
4
  * The stored document is flat: `components[]` carry `process` (runtime unit),
5
- * `purl` (repo/package), `construct`, `role`, `module`, plus `relations[]`
6
- * (static) and `walkthroughs[]` (dynamic). C4 wants a hierarchy above the
5
+ * `purl` (repo/package), `construct`, `role`, `module`, plus `walkthroughs[]`
6
+ * (dynamic). C4 wants a hierarchy above the
7
7
  * component — system → container → component — with externals and actors
8
8
  * outside it. This module derives that hierarchy without inventing data:
9
9
  *
@@ -59,12 +59,12 @@ export interface C4Group {
59
59
  memberIds: string[];
60
60
  }
61
61
 
62
- /** A rolled-up collaboration. `relationship` = static, `flow` = walkthrough. */
62
+ /** A rolled-up collaboration — a walkthrough flow between owners. */
63
63
  export interface C4Edge {
64
64
  id: string;
65
65
  source: string;
66
66
  target: string;
67
- kind: 'relationship' | 'flow';
67
+ kind: 'flow';
68
68
  label: string;
69
69
  mechanisms: string[];
70
70
  count: number;
@@ -234,7 +234,6 @@ export function toC4(doc: SubsystemModelDocument, options: ToC4Options = {}): C4
234
234
  }
235
235
 
236
236
  // --- Edges: roll each endpoint up to its owner at this view -------------
237
- const relEdges = new Map<string, C4Edge>();
238
237
  const flowEdges = new Map<string, C4Edge>();
239
238
 
240
239
  const addEdge = (
@@ -255,16 +254,13 @@ export function toC4(doc: SubsystemModelDocument, options: ToC4Options = {}): C4
255
254
  if (!edge.mechanisms.includes(mechanism)) edge.mechanisms.push(mechanism);
256
255
  };
257
256
 
258
- for (const r of doc.relations ?? []) {
259
- addEdge(relEdges, ownerOf.get(r.from), ownerOf.get(r.to), 'relationship', r.relationType);
260
- }
261
257
  for (const w of doc.walkthroughs ?? []) {
262
258
  for (const s of w.steps ?? []) {
263
259
  addEdge(flowEdges, ownerOf.get(s.from), ownerOf.get(s.to), 'flow', s.mechanism);
264
260
  }
265
261
  }
266
262
 
267
- const edges = [...relEdges.values(), ...flowEdges.values()];
263
+ const edges = [...flowEdges.values()];
268
264
  for (const e of edges) e.label = [...e.mechanisms].sort().join(' + ');
269
265
 
270
266
  return {
@@ -759,6 +759,16 @@ export async function computeElkLayout(
759
759
  if (parentId && builtGroups.has(parentId)) continue; // nested inside parent
760
760
  elkParents.push(node);
761
761
  }
762
+ // Order root-level compounds by model order (the caller's `groups` array), so
763
+ // disconnected sibling frames lay out deterministically — e.g. `app/book`
764
+ // before `lib`. Without this, planCompoundGroups' bottom-up build order
765
+ // decides placement.
766
+ const groupOrder = new Map(groupDefs.map((g, i) => [g.id, i]));
767
+ elkParents.sort(
768
+ (a, b) =>
769
+ (groupOrder.get(a.id) ?? Number.MAX_SAFE_INTEGER) -
770
+ (groupOrder.get(b.id) ?? Number.MAX_SAFE_INTEGER),
771
+ );
762
772
 
763
773
  // Create ELK graph
764
774
  const rootOptions = getElkOptions(options);