@principal-ai/subsystems-react 0.24.0 → 0.24.2

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 (46) hide show
  1. package/dist/index.d.ts +7 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +4 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/subsystem/ComponentDeclaration.d.ts +3 -1
  6. package/dist/subsystem/ComponentDeclaration.d.ts.map +1 -1
  7. package/dist/subsystem/ComponentDeclaration.js +2 -2
  8. package/dist/subsystem/ComponentDeclaration.js.map +1 -1
  9. package/dist/subsystem/ConstructsCatalog.d.ts +30 -0
  10. package/dist/subsystem/ConstructsCatalog.d.ts.map +1 -0
  11. package/dist/subsystem/ConstructsCatalog.js +329 -0
  12. package/dist/subsystem/ConstructsCatalog.js.map +1 -0
  13. package/dist/subsystem/DiagnosticToggle.d.ts +46 -0
  14. package/dist/subsystem/DiagnosticToggle.d.ts.map +1 -0
  15. package/dist/subsystem/DiagnosticToggle.js +95 -0
  16. package/dist/subsystem/DiagnosticToggle.js.map +1 -0
  17. package/dist/subsystem/IssueList.d.ts +103 -0
  18. package/dist/subsystem/IssueList.d.ts.map +1 -0
  19. package/dist/subsystem/IssueList.js +310 -0
  20. package/dist/subsystem/IssueList.js.map +1 -0
  21. package/dist/subsystem/SubsystemComponentGraph.d.ts +28 -0
  22. package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -1
  23. package/dist/subsystem/SubsystemComponentGraph.js +81 -58
  24. package/dist/subsystem/SubsystemComponentGraph.js.map +1 -1
  25. package/dist/subsystem/SubsystemFileTree.js +2 -2
  26. package/dist/subsystem/SubsystemFileTree.js.map +1 -1
  27. package/dist/subsystem/model.d.ts +13 -2
  28. package/dist/subsystem/model.d.ts.map +1 -1
  29. package/dist/subsystem/model.js +12 -0
  30. package/dist/subsystem/model.js.map +1 -1
  31. package/dist/subsystem/nodes.js +5 -5
  32. package/dist/subsystem/nodes.js.map +1 -1
  33. package/package.json +1 -1
  34. package/src/index.ts +37 -0
  35. package/src/stories/Subsystem/ComponentGraph/Constructs.stories.tsx +287 -0
  36. package/src/stories/Subsystem/ComponentGraph/Diagnostics.stories.tsx +138 -0
  37. package/src/stories/Subsystem/ComponentGraph/Issues.stories.tsx +130 -0
  38. package/src/subsystem/ComponentDeclaration.tsx +4 -1
  39. package/src/subsystem/ConstructsCatalog.tsx +604 -0
  40. package/src/subsystem/DiagnosticToggle.tsx +160 -0
  41. package/src/subsystem/IssueList.tsx +519 -0
  42. package/src/subsystem/SubsystemComponentGraph.tsx +119 -38
  43. package/src/subsystem/SubsystemFileTree.tsx +2 -2
  44. package/src/subsystem/model.test.ts +34 -0
  45. package/src/subsystem/model.ts +18 -2
  46. package/src/subsystem/nodes.tsx +5 -5
@@ -0,0 +1,46 @@
1
+ /**
2
+ * DiagnosticToggle — the subsystem graph's status/report chip.
3
+ *
4
+ * A compact button that lives in the sidebar title row (beside the description
5
+ * toggle). It carries the *status* of the graph's last verification pass in its
6
+ * icon color + count and, on click, opens the full report (the host owns that
7
+ * report; this component only surfaces state and calls `onOpen`).
8
+ *
9
+ * Status → color (theme):
10
+ * - `ok` → success (green)
11
+ * - `issues` → error (red)
12
+ * - `gaps` → warning (amber) — nothing failed, but some claims are unconfirmed
13
+ * - `unknown` → muted (never checked)
14
+ *
15
+ * `stale` means the inputs changed since the report was produced — the color
16
+ * stays, a hollow ring marks it. `busy` swaps the icon for a spinner.
17
+ */
18
+ /// <reference types="react" />
19
+ export type SubsystemDiagnosticStatus = 'ok' | 'issues' | 'gaps' | 'unknown';
20
+ export interface SubsystemDiagnostic {
21
+ status: SubsystemDiagnosticStatus;
22
+ /** Count shown beside the icon (e.g. error + warn findings). Hidden when 0/undefined. */
23
+ issueCount?: number;
24
+ /** Inputs changed since the report was produced. */
25
+ stale?: boolean;
26
+ /** A verification pass is running right now. */
27
+ busy?: boolean;
28
+ /** Tooltip / a11y label override; otherwise derived from `status`. */
29
+ title?: string;
30
+ /** Click — open the report. */
31
+ onOpen?: () => void;
32
+ }
33
+ /** Resolve the status accent from the active theme. */
34
+ export declare function diagnosticStatusColor(status: SubsystemDiagnosticStatus, colors: {
35
+ success: string;
36
+ error: string;
37
+ warning: string;
38
+ }, muted: string): string;
39
+ /** Human tooltip for the current diagnostic state. */
40
+ export declare function diagnosticTitle(diagnostic: SubsystemDiagnostic): string;
41
+ export interface SubsystemDiagnosticToggleProps extends SubsystemDiagnostic {
42
+ /** Icon size in px. @default 14 */
43
+ size?: number;
44
+ }
45
+ export declare function SubsystemDiagnosticToggle({ status, issueCount, stale, busy, size, onOpen, ...rest }: SubsystemDiagnosticToggleProps): import("react").JSX.Element;
46
+ //# sourceMappingURL=DiagnosticToggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiagnosticToggle.d.ts","sourceRoot":"","sources":["../../src/subsystem/DiagnosticToggle.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;;AAMH,MAAM,MAAM,yBAAyB,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,yBAAyB,CAAC;IAClC,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,uDAAuD;AACvD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC3D,KAAK,EAAE,MAAM,GACZ,MAAM,CAKR;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAmBvE;AAED,MAAM,WAAW,8BAA+B,SAAQ,mBAAmB;IACzE,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,yBAAyB,CAAC,EACxC,MAAM,EACN,UAAU,EACV,KAAa,EACb,IAAY,EACZ,IAAS,EACT,MAAM,EACN,GAAG,IAAI,EACR,EAAE,8BAA8B,+BA0EhC"}
@@ -0,0 +1,95 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * DiagnosticToggle — the subsystem graph's status/report chip.
4
+ *
5
+ * A compact button that lives in the sidebar title row (beside the description
6
+ * toggle). It carries the *status* of the graph's last verification pass in its
7
+ * icon color + count and, on click, opens the full report (the host owns that
8
+ * report; this component only surfaces state and calls `onOpen`).
9
+ *
10
+ * Status → color (theme):
11
+ * - `ok` → success (green)
12
+ * - `issues` → error (red)
13
+ * - `gaps` → warning (amber) — nothing failed, but some claims are unconfirmed
14
+ * - `unknown` → muted (never checked)
15
+ *
16
+ * `stale` means the inputs changed since the report was produced — the color
17
+ * stays, a hollow ring marks it. `busy` swaps the icon for a spinner.
18
+ */
19
+ import { useState } from 'react';
20
+ import { Activity, Loader2 } from 'lucide-react';
21
+ import { useTheme } from '@principal-ade/industry-theme';
22
+ /** Resolve the status accent from the active theme. */
23
+ export function diagnosticStatusColor(status, colors, muted) {
24
+ if (status === 'ok')
25
+ return colors.success;
26
+ if (status === 'issues')
27
+ return colors.error;
28
+ if (status === 'gaps')
29
+ return colors.warning;
30
+ return muted;
31
+ }
32
+ /** Human tooltip for the current diagnostic state. */
33
+ export function diagnosticTitle(diagnostic) {
34
+ if (diagnostic.title)
35
+ return diagnostic.title;
36
+ const { status, issueCount, stale, busy } = diagnostic;
37
+ let head;
38
+ if (status === 'ok')
39
+ head = 'Diagnostics: no issues';
40
+ else if (status === 'issues')
41
+ head =
42
+ issueCount != null && issueCount > 0
43
+ ? `Diagnostics: ${issueCount} issue${issueCount === 1 ? '' : 's'}`
44
+ : 'Diagnostics: issues found';
45
+ else if (status === 'gaps')
46
+ head =
47
+ issueCount != null && issueCount > 0
48
+ ? `Diagnostics: ${issueCount} unconfirmed`
49
+ : 'Diagnostics: unconfirmed claims';
50
+ else
51
+ head = 'Diagnostics: not checked yet';
52
+ if (busy)
53
+ return `${head} — checking…`;
54
+ if (stale)
55
+ return `${head} (stale) — open for details`;
56
+ return `${head} — open report`;
57
+ }
58
+ export function SubsystemDiagnosticToggle({ status, issueCount, stale = false, busy = false, size = 14, onOpen, ...rest }) {
59
+ const { theme } = useTheme();
60
+ const [hover, setHover] = useState(false);
61
+ const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
62
+ const color = diagnosticStatusColor(status, theme.colors, muted);
63
+ const label = diagnosticTitle({ status, issueCount, stale, busy, ...rest });
64
+ const showCount = issueCount != null && issueCount > 0;
65
+ return (_jsxs(_Fragment, { children: [busy && (_jsx("style", { children: '@keyframes subsystem-diagnostic-spin{to{transform:rotate(360deg)}}' })), _jsxs("button", { type: "button", onClick: onOpen, onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), title: label, "aria-label": label, "aria-haspopup": "dialog", style: {
66
+ display: 'inline-flex',
67
+ alignItems: 'center',
68
+ gap: 4,
69
+ height: 22,
70
+ padding: showCount ? '0 7px 0 6px' : '0 5px',
71
+ border: 'none',
72
+ borderRadius: 4,
73
+ background: hover ? theme.colors.border : 'transparent',
74
+ color,
75
+ cursor: 'pointer',
76
+ flexShrink: 0,
77
+ transition: 'background 120ms ease, opacity 120ms ease',
78
+ opacity: stale && !busy ? 0.55 : 1,
79
+ }, children: [_jsxs("span", { style: { position: 'relative', display: 'inline-flex' }, children: [busy ? (_jsx(Loader2, { size: size, style: { animation: 'subsystem-diagnostic-spin 900ms linear infinite' } })) : (_jsx(Activity, { size: size })), stale && !busy && (_jsx("span", { "aria-hidden": true, style: {
80
+ position: 'absolute',
81
+ top: -2,
82
+ right: -2,
83
+ width: 6,
84
+ height: 6,
85
+ borderRadius: '50%',
86
+ border: `1.5px solid ${color}`,
87
+ background: theme.colors.backgroundSecondary ?? theme.colors.background,
88
+ } }))] }), showCount && (_jsx("span", { style: {
89
+ fontFamily: theme.fonts.monospace,
90
+ fontSize: theme.fontSizes[0],
91
+ fontWeight: 600,
92
+ lineHeight: 1,
93
+ }, children: issueCount }))] })] }));
94
+ }
95
+ //# sourceMappingURL=DiagnosticToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiagnosticToggle.js","sourceRoot":"","sources":["../../src/subsystem/DiagnosticToggle.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * SubsystemIssueList — the diagnostics sidebar list.
3
+ *
4
+ * A catalogue of verification issues (audit findings), grouped by *target* so
5
+ * every broken component / relation / module / flow clusters together. Each
6
+ * card is severity-colored, names its kind, states the message, and offers the
7
+ * deterministic fix inline when one exists.
8
+ *
9
+ * The list is presentation-only: it owns no verification logic. Hosts map their
10
+ * findings into `SubsystemIssue[]` and handle `onSelectIssue` / `onApplyFix`
11
+ * (e.g. focus the node on the graph, or apply the fix in the report).
12
+ */
13
+ /// <reference types="react" />
14
+ export type SubsystemIssueSeverity = 'error' | 'warn' | 'info';
15
+ export type SubsystemIssueTargetKind = 'component' | 'relation' | 'module' | 'walkthrough' | 'graph';
16
+ /**
17
+ * The four verification layers, in order. Mirrors the docs' progression:
18
+ * constructs → static topology → runtime topology → walkthrough.
19
+ */
20
+ export type SubsystemIssueCategory = 'construct' | 'static-topology' | 'runtime-topology' | 'walkthrough';
21
+ /** Layer order + display names, shared by the list and its headers. */
22
+ export declare const SUBSYSTEM_ISSUE_CATEGORIES: SubsystemIssueCategory[];
23
+ export declare const SUBSYSTEM_ISSUE_CATEGORY_LABEL: Record<SubsystemIssueCategory, string>;
24
+ /**
25
+ * Verification layer for an issue. An explicit `category` wins; otherwise the
26
+ * audit `kind` is mapped, defaulting to `construct` (the base layer).
27
+ */
28
+ export declare function issueCategory(issue: SubsystemIssue): SubsystemIssueCategory;
29
+ export interface SubsystemIssueTarget {
30
+ kind: SubsystemIssueTargetKind;
31
+ /** Stable id used to group and to focus the target on the graph. */
32
+ id?: string;
33
+ /** Display label (component name, `from → to`, module path, flow title). */
34
+ label: string;
35
+ /** Optional sub-label (relation type, step number, …). */
36
+ detail?: string;
37
+ }
38
+ /** One issue to surface in the sidebar (and later, on the graph). */
39
+ export interface SubsystemIssue {
40
+ id: string;
41
+ severity: SubsystemIssueSeverity;
42
+ /** Machine kind, e.g. `missing_file`. Drives the label when `kindLabel` is absent. */
43
+ kind: string;
44
+ /** Human label override for the kind. */
45
+ kindLabel?: string;
46
+ message: string;
47
+ target?: SubsystemIssueTarget;
48
+ /** Verification layer override; defaults from `kind`. */
49
+ category?: SubsystemIssueCategory;
50
+ /** Deterministic fix the user can apply without an agent. */
51
+ fix?: {
52
+ label: string;
53
+ };
54
+ }
55
+ /** `missing_file` → `Missing file`. */
56
+ export declare function humanizeIssueKind(kind: string): string;
57
+ /** Label for an issue's kind. Explicit `kindLabel` wins; unknown kinds humanize. */
58
+ export declare function issueKindLabel(issue: SubsystemIssue): string;
59
+ export declare function severityRank(severity: SubsystemIssueSeverity): number;
60
+ /** Worst (most severe) severity in a list; `info` for an empty list. */
61
+ export declare function worstSeverity(issues: SubsystemIssue[]): SubsystemIssueSeverity;
62
+ export interface SubsystemIssueGroup {
63
+ key: string;
64
+ kind: SubsystemIssueTargetKind;
65
+ label: string;
66
+ detail?: string;
67
+ issues: SubsystemIssue[];
68
+ severity: SubsystemIssueSeverity;
69
+ }
70
+ /**
71
+ * Group issues by their target, worst-severity first, then by label. Within a
72
+ * group, issues are ordered error → warn → info (stable for ties).
73
+ */
74
+ export declare function groupIssuesByTarget(issues: SubsystemIssue[]): SubsystemIssueGroup[];
75
+ export interface SubsystemIssueCategoryGroup {
76
+ category: SubsystemIssueCategory;
77
+ label: string;
78
+ issues: SubsystemIssue[];
79
+ /** Worst severity present; `null` when the layer is clean. */
80
+ severity: SubsystemIssueSeverity | null;
81
+ count: number;
82
+ }
83
+ /**
84
+ * Group issues into the four verification layers — always all four, in order,
85
+ * so a clean layer can render its "happy" state. Issues within a layer are
86
+ * ordered error → warn → info (stable for ties).
87
+ */
88
+ export declare function groupIssuesByCategory(issues: SubsystemIssue[]): SubsystemIssueCategoryGroup[];
89
+ export interface SubsystemIssueCardProps {
90
+ issue: SubsystemIssue;
91
+ onSelect?: (issue: SubsystemIssue) => void;
92
+ onApplyFix?: (issue: SubsystemIssue) => void;
93
+ onHover?: (issue: SubsystemIssue | null) => void;
94
+ }
95
+ export declare function SubsystemIssueCard({ issue, onSelect, onApplyFix, onHover, }: SubsystemIssueCardProps): import("react").JSX.Element;
96
+ export interface SubsystemIssueListProps {
97
+ issues: SubsystemIssue[];
98
+ onSelectIssue?: (issue: SubsystemIssue) => void;
99
+ onApplyFix?: (issue: SubsystemIssue) => void;
100
+ onHoverIssue?: (issue: SubsystemIssue | null) => void;
101
+ }
102
+ export declare function SubsystemIssueList({ issues, onSelectIssue, onApplyFix, onHoverIssue, }: SubsystemIssueListProps): import("react").JSX.Element;
103
+ //# sourceMappingURL=IssueList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IssueList.d.ts","sourceRoot":"","sources":["../../src/subsystem/IssueList.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,310 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * SubsystemIssueList — the diagnostics sidebar list.
4
+ *
5
+ * A catalogue of verification issues (audit findings), grouped by *target* so
6
+ * every broken component / relation / module / flow clusters together. Each
7
+ * card is severity-colored, names its kind, states the message, and offers the
8
+ * deterministic fix inline when one exists.
9
+ *
10
+ * The list is presentation-only: it owns no verification logic. Hosts map their
11
+ * findings into `SubsystemIssue[]` and handle `onSelectIssue` / `onApplyFix`
12
+ * (e.g. focus the node on the graph, or apply the fix in the report).
13
+ */
14
+ import { useState } from 'react';
15
+ import { ChevronDown, ChevronRight, CircleCheck, Wrench, } from 'lucide-react';
16
+ import { useTheme } from '@principal-ade/industry-theme';
17
+ /** Layer order + display names, shared by the list and its headers. */
18
+ export const SUBSYSTEM_ISSUE_CATEGORIES = [
19
+ 'construct',
20
+ 'static-topology',
21
+ 'runtime-topology',
22
+ 'walkthrough',
23
+ ];
24
+ export const SUBSYSTEM_ISSUE_CATEGORY_LABEL = {
25
+ construct: 'Constructs',
26
+ 'static-topology': 'Static topology',
27
+ 'runtime-topology': 'Runtime topology',
28
+ walkthrough: 'Walkthrough',
29
+ };
30
+ /** Default `kind` → layer. `boundary_*` splits by module (static) vs process (runtime). */
31
+ const KIND_CATEGORY = {
32
+ missing_file: 'construct',
33
+ missing_symbol: 'construct',
34
+ stale_declaration: 'construct',
35
+ construct_mismatch: 'construct',
36
+ construct_unconfirmed: 'construct',
37
+ signature_mismatch: 'construct',
38
+ signature_unconfirmed: 'construct',
39
+ anchor: 'construct',
40
+ unresolved: 'construct',
41
+ topology_broken_endpoint: 'static-topology',
42
+ topology_import_unconfirmed: 'static-topology',
43
+ topology_relation_unconfirmed: 'static-topology',
44
+ boundary_module_without_file: 'static-topology',
45
+ boundary_module_file_mismatch: 'static-topology',
46
+ boundary_process_nest_disagree: 'runtime-topology',
47
+ walkthrough: 'walkthrough',
48
+ };
49
+ /**
50
+ * Verification layer for an issue. An explicit `category` wins; otherwise the
51
+ * audit `kind` is mapped, defaulting to `construct` (the base layer).
52
+ */
53
+ export function issueCategory(issue) {
54
+ return issue.category ?? KIND_CATEGORY[issue.kind] ?? 'construct';
55
+ }
56
+ const SEVERITY_RANK = {
57
+ error: 0,
58
+ warn: 1,
59
+ info: 2,
60
+ };
61
+ /** `missing_file` → `Missing file`. */
62
+ export function humanizeIssueKind(kind) {
63
+ const spaced = kind.replace(/[_-]+/g, ' ').trim();
64
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
65
+ }
66
+ /**
67
+ * Curated short labels, trimmed of prefixes the grouping already implies
68
+ * (`topology_`, `boundary_`) but kept unambiguous within a layer — so
69
+ * `construct_mismatch` reads "Wrong construct", not a bare "Mismatch" that
70
+ * would collide with `signature_mismatch`. Explicit `issue.kindLabel` wins.
71
+ */
72
+ const KIND_LABEL = {
73
+ missing_file: 'Missing file',
74
+ missing_symbol: 'Missing symbol',
75
+ stale_declaration: 'Stale declaration',
76
+ construct_mismatch: 'Wrong construct',
77
+ construct_unconfirmed: 'Unconfirmed construct',
78
+ signature_mismatch: 'Signature mismatch',
79
+ signature_unconfirmed: 'Signature unconfirmed',
80
+ anchor: 'Anchor',
81
+ unresolved: 'Unresolved',
82
+ topology_broken_endpoint: 'Broken endpoint',
83
+ topology_import_unconfirmed: 'Import unconfirmed',
84
+ topology_relation_unconfirmed: 'Relation unconfirmed',
85
+ boundary_module_without_file: 'Module without file',
86
+ boundary_module_file_mismatch: 'Module file mismatch',
87
+ boundary_process_nest_disagree: 'Process nest disagree',
88
+ walkthrough: 'Step issue',
89
+ };
90
+ /** Label for an issue's kind. Explicit `kindLabel` wins; unknown kinds humanize. */
91
+ export function issueKindLabel(issue) {
92
+ return issue.kindLabel ?? KIND_LABEL[issue.kind] ?? humanizeIssueKind(issue.kind);
93
+ }
94
+ export function severityRank(severity) {
95
+ return SEVERITY_RANK[severity] ?? SEVERITY_RANK.info;
96
+ }
97
+ /** Worst (most severe) severity in a list; `info` for an empty list. */
98
+ export function worstSeverity(issues) {
99
+ let worst = 'info';
100
+ for (const issue of issues) {
101
+ if (severityRank(issue.severity) < severityRank(worst))
102
+ worst = issue.severity;
103
+ }
104
+ return worst;
105
+ }
106
+ function targetKey(issue) {
107
+ const t = issue.target;
108
+ if (!t)
109
+ return 'graph';
110
+ return `${t.kind}:${t.id ?? t.label}`;
111
+ }
112
+ /**
113
+ * Group issues by their target, worst-severity first, then by label. Within a
114
+ * group, issues are ordered error → warn → info (stable for ties).
115
+ */
116
+ export function groupIssuesByTarget(issues) {
117
+ const byKey = new Map();
118
+ for (const issue of issues) {
119
+ const key = targetKey(issue);
120
+ let group = byKey.get(key);
121
+ if (!group) {
122
+ group = {
123
+ key,
124
+ kind: issue.target?.kind ?? 'graph',
125
+ label: issue.target?.label ?? 'Model',
126
+ detail: issue.target?.detail,
127
+ issues: [],
128
+ severity: 'info',
129
+ };
130
+ byKey.set(key, group);
131
+ }
132
+ group.issues.push(issue);
133
+ }
134
+ const groups = [...byKey.values()];
135
+ for (const group of groups) {
136
+ group.issues.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
137
+ group.severity = worstSeverity(group.issues);
138
+ }
139
+ groups.sort((a, b) => {
140
+ const bySeverity = severityRank(a.severity) - severityRank(b.severity);
141
+ if (bySeverity !== 0)
142
+ return bySeverity;
143
+ return a.label.localeCompare(b.label);
144
+ });
145
+ return groups;
146
+ }
147
+ /**
148
+ * Group issues into the four verification layers — always all four, in order,
149
+ * so a clean layer can render its "happy" state. Issues within a layer are
150
+ * ordered error → warn → info (stable for ties).
151
+ */
152
+ export function groupIssuesByCategory(issues) {
153
+ const byCategory = new Map();
154
+ for (const category of SUBSYSTEM_ISSUE_CATEGORIES)
155
+ byCategory.set(category, []);
156
+ for (const issue of issues) {
157
+ byCategory.get(issueCategory(issue))?.push(issue);
158
+ }
159
+ return SUBSYSTEM_ISSUE_CATEGORIES.map((category) => {
160
+ const grouped = byCategory.get(category) ?? [];
161
+ grouped.sort((a, b) => severityRank(a.severity) - severityRank(b.severity));
162
+ return {
163
+ category,
164
+ label: SUBSYSTEM_ISSUE_CATEGORY_LABEL[category],
165
+ issues: grouped,
166
+ severity: grouped.length > 0 ? worstSeverity(grouped) : null,
167
+ count: grouped.length,
168
+ };
169
+ });
170
+ }
171
+ function severityColor(severity, colors, muted) {
172
+ if (severity === 'error')
173
+ return colors.error ?? '#e5534b';
174
+ if (severity === 'warn')
175
+ return colors.warning ?? '#d4a017';
176
+ return colors.info ?? muted;
177
+ }
178
+ const TARGET_KIND_LABEL = {
179
+ component: 'component',
180
+ relation: 'relation',
181
+ module: 'module',
182
+ walkthrough: 'flow',
183
+ graph: 'model',
184
+ };
185
+ export function SubsystemIssueCard({ issue, onSelect, onApplyFix, onHover, }) {
186
+ const { theme } = useTheme();
187
+ const [hover, setHover] = useState(false);
188
+ // Every issue is collapsed to its kind by default so the list scans as a
189
+ // catalogue of problems; clicking a card reveals the message and any fix.
190
+ const [expanded, setExpanded] = useState(false);
191
+ const showDetail = expanded;
192
+ const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
193
+ const color = severityColor(issue.severity, theme.colors, muted);
194
+ const activate = () => {
195
+ setExpanded((v) => !v);
196
+ onSelect?.(issue);
197
+ };
198
+ return (_jsxs("div", { role: "button", tabIndex: 0, "aria-expanded": expanded, onClick: activate, onKeyDown: (e) => {
199
+ if (e.key === 'Enter' || e.key === ' ') {
200
+ e.preventDefault();
201
+ activate();
202
+ }
203
+ }, onMouseEnter: () => {
204
+ setHover(true);
205
+ onHover?.(issue);
206
+ }, onMouseLeave: () => {
207
+ setHover(false);
208
+ onHover?.(null);
209
+ }, style: {
210
+ display: 'flex',
211
+ flexDirection: 'column',
212
+ gap: 5,
213
+ padding: '9px 12px 10px',
214
+ borderBottom: `1px solid ${theme.colors.border}`,
215
+ background: hover ? theme.colors.background : 'transparent',
216
+ cursor: 'pointer',
217
+ transition: 'background 120ms ease',
218
+ fontFamily: theme.fonts.body,
219
+ }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'flex-start', gap: 6, minWidth: 0 }, children: [_jsxs("div", { style: {
220
+ flex: 1,
221
+ minWidth: 0,
222
+ display: 'flex',
223
+ flexDirection: 'column',
224
+ gap: 1,
225
+ }, children: [_jsx("span", { style: {
226
+ fontFamily: theme.fonts.monospace,
227
+ fontSize: theme.fontSizes[0],
228
+ fontWeight: 600,
229
+ letterSpacing: 0.3,
230
+ textTransform: 'uppercase',
231
+ color,
232
+ whiteSpace: 'nowrap',
233
+ }, children: issueKindLabel(issue) }), issue.target && (_jsx("span", { style: {
234
+ minWidth: 0,
235
+ fontFamily: theme.fonts.monospace,
236
+ fontSize: theme.fontSizes[0],
237
+ color: theme.colors.text,
238
+ whiteSpace: 'nowrap',
239
+ overflow: 'hidden',
240
+ textOverflow: 'ellipsis',
241
+ }, title: `${TARGET_KIND_LABEL[issue.target.kind]} · ${issue.target.label}`, children: issue.target.label }))] }), _jsx("span", { style: {
242
+ display: 'inline-flex',
243
+ color: muted,
244
+ flexShrink: 0,
245
+ marginTop: 1,
246
+ }, children: expanded ? _jsx(ChevronDown, { size: 13 }) : _jsx(ChevronRight, { size: 13 }) })] }), showDetail && (_jsx("div", { style: {
247
+ fontSize: theme.fontSizes[0],
248
+ color: theme.colors.text,
249
+ lineHeight: 1.45,
250
+ overflowWrap: 'anywhere',
251
+ }, children: issue.message })), showDetail && issue.fix && (_jsx("div", { style: { display: 'flex', marginTop: 1 }, children: _jsxs("button", { type: "button", onClick: (e) => {
252
+ e.stopPropagation();
253
+ onApplyFix?.(issue);
254
+ }, disabled: onApplyFix == null, style: {
255
+ display: 'inline-flex',
256
+ alignItems: 'center',
257
+ gap: 5,
258
+ padding: '3px 8px',
259
+ border: `1px solid ${theme.colors.primary}`,
260
+ borderRadius: 4,
261
+ background: 'transparent',
262
+ color: theme.colors.primary,
263
+ fontFamily: theme.fonts.monospace,
264
+ fontSize: theme.fontSizes[0],
265
+ cursor: onApplyFix == null ? 'default' : 'pointer',
266
+ opacity: onApplyFix == null ? 0.5 : 1,
267
+ }, children: [_jsx(Wrench, { size: 12 }), issue.fix.label] }) }))] }));
268
+ }
269
+ export function SubsystemIssueList({ issues, onSelectIssue, onApplyFix, onHoverIssue, }) {
270
+ const { theme } = useTheme();
271
+ const muted = theme.colors.textMuted ?? theme.colors.textSecondary;
272
+ const categories = groupIssuesByCategory(issues);
273
+ return (_jsx("div", { style: { flex: 1, minHeight: 0, overflowY: 'auto' }, children: categories.map((category) => {
274
+ // A layer with no findings renders its happy state: a green check in
275
+ // the header, no count, no cards.
276
+ const clean = category.count === 0;
277
+ const accent = category.severity
278
+ ? severityColor(category.severity, theme.colors, muted)
279
+ : theme.colors.success;
280
+ return (_jsxs("div", { children: [_jsxs("div", { style: {
281
+ position: 'sticky',
282
+ top: 0,
283
+ zIndex: 1,
284
+ display: 'flex',
285
+ alignItems: 'center',
286
+ gap: 7,
287
+ padding: '7px 12px',
288
+ background: theme.colors.backgroundSecondary ?? theme.colors.background,
289
+ borderBottom: `1px solid ${theme.colors.border}`,
290
+ }, children: [_jsx("span", { style: {
291
+ flex: 1,
292
+ minWidth: 0,
293
+ fontSize: theme.fontSizes[1],
294
+ fontWeight: 600,
295
+ color: clean ? muted : theme.colors.text,
296
+ fontFamily: theme.fonts.body,
297
+ whiteSpace: 'nowrap',
298
+ overflow: 'hidden',
299
+ textOverflow: 'ellipsis',
300
+ }, children: category.label }), clean ? (_jsx(CircleCheck, { size: 13, color: accent, style: { flexShrink: 0 } })) : (_jsx("span", { style: {
301
+ fontFamily: theme.fonts.monospace,
302
+ fontSize: theme.fontSizes[0],
303
+ fontWeight: 600,
304
+ color: accent,
305
+ flexShrink: 0,
306
+ }, children: category.count }))] }), !clean &&
307
+ category.issues.map((issue) => (_jsx(SubsystemIssueCard, { issue: issue, onSelect: onSelectIssue, onApplyFix: onApplyFix, onHover: onHoverIssue }, issue.id)))] }, category.category));
308
+ }) }));
309
+ }
310
+ //# sourceMappingURL=IssueList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IssueList.js","sourceRoot":"","sources":["../../src/subsystem/IssueList.tsx"],"names":[],"mappings":"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"}
@@ -7,6 +7,9 @@
7
7
  * inside one labeled boundary frame; nodes without one sit outside every
8
8
  * boundary. Clicking a component invokes `onSelect`.
9
9
  *
10
+ * When the model has components but no topology or walkthrough edges, the
11
+ * canvas is a constructs catalog (list + signature) instead of a graph.
12
+ *
10
13
  * This is a focused fork of the package's `GraphRenderer` pipeline (same ELK
11
14
  * edge routing, delayed fitView, Background/Controls/MiniMap, node/edge type
12
15
  * injection, onNodeClick) adapted to the subsystem model — read-only.
@@ -14,6 +17,8 @@
14
17
  import type { ReactNode } from 'react';
15
18
  import { type SubsystemComponentEdge, type SubsystemComponent, type SubsystemEdgeView, type SubsystemRelation, type SubsystemWalkthrough } from './model';
16
19
  import type { SubsystemOpenFileOptions } from './declarationRef';
20
+ import { type SubsystemDiagnostic } from './DiagnosticToggle';
21
+ import { type SubsystemIssue } from './IssueList';
17
22
  import type { ComponentVerificationState } from './ComponentDeclaration';
18
23
  /** Context passed to `renderWalkthroughViewer` when a flow/step is focused. */
19
24
  export interface WalkthroughViewerContext {
@@ -103,6 +108,29 @@ export interface SubsystemComponentGraphProps {
103
108
  sidebarExtra?: ReactNode;
104
109
  /** Rendered in the sidebar under the description (e.g. selection inspector). */
105
110
  sidebarAfterDescription?: ReactNode;
111
+ /**
112
+ * Diagnostics status chip in the sidebar title row (beside the description
113
+ * toggle). Shows the last verification pass's state as an icon color + count;
114
+ * `onOpen` opens the full report. Omit to hide the chip.
115
+ */
116
+ diagnostic?: SubsystemDiagnostic;
117
+ /**
118
+ * Verification issues for this graph (audit findings). When diagnostics are
119
+ * active (see `showIssues`) the sidebar's bottom panel becomes the issue
120
+ * list instead of the file tree / walkthroughs.
121
+ */
122
+ issues?: SubsystemIssue[];
123
+ /**
124
+ * Force the sidebar into diagnostics mode. Defaults to `true` whenever
125
+ * `issues` is non-empty (and nothing else has been forced).
126
+ */
127
+ showIssues?: boolean;
128
+ /** Click an issue — focus its target on the graph / open detail. */
129
+ onSelectIssue?: (issue: SubsystemIssue) => void;
130
+ /** Apply an issue's deterministic fix. */
131
+ onApplyIssueFix?: (issue: SubsystemIssue) => void;
132
+ /** Hover an issue — transiently highlight its target (null on leave). */
133
+ onHoverIssue?: (issue: SubsystemIssue | null) => void;
106
134
  /**
107
135
  * Host-injected reader/renderer for the bottom file drawer, keyed by
108
136
  * repo-root-relative path. Opening happens on declaration/file-tree clicks.