graphlin 0.1.2 → 0.2.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +12 -3
- package/docs/decision-service.md +393 -0
- package/docs/extension-authoring.md +553 -0
- package/docs/model-api.md +293 -0
- package/docs/usage.md +465 -0
- package/docs/visualizer-views.md +199 -0
- package/node_modules/@vscode/tree-sitter-wasm/LICENSE +21 -0
- package/node_modules/@vscode/tree-sitter-wasm/README.md +36 -0
- package/node_modules/@vscode/tree-sitter-wasm/SECURITY.md +41 -0
- package/node_modules/@vscode/tree-sitter-wasm/cgmanifest.json +16 -0
- package/node_modules/@vscode/tree-sitter-wasm/package.json +42 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-c-sharp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-cpp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-go.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-java.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-javascript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-php.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-python.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ruby.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-rust.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-tsx.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js +4075 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter.d.ts +1027 -0
- package/package.json +74 -9
- package/plugin.json +4 -2
- package/runtime/core/evidence.mjs +43 -9
- package/runtime/core/graph.mjs +11 -6
- package/runtime/core/privacy.mjs +1 -0
- package/runtime/daemon/auth.mjs +7 -3
- package/runtime/daemon/diagnostics.mjs +1 -1
- package/runtime/daemon/extension-api.mjs +203 -0
- package/runtime/daemon/lineage.mjs +70 -0
- package/runtime/daemon/manager.mjs +9 -6
- package/runtime/daemon/model-api.mjs +728 -0
- package/runtime/daemon/model-persistence.mjs +220 -0
- package/runtime/daemon/server.mjs +70 -12
- package/runtime/daemon/settings.mjs +11 -3
- package/runtime/decisions/broker.mjs +349 -0
- package/runtime/decisions/contracts.mjs +179 -0
- package/runtime/decisions/evaluation.mjs +305 -0
- package/runtime/decisions/faults.mjs +32 -0
- package/runtime/decisions/index.mjs +818 -0
- package/runtime/decisions/profiles.mjs +93 -0
- package/runtime/decisions/questions.mjs +268 -0
- package/runtime/discovery/index.mjs +2 -0
- package/runtime/discovery/inventory.mjs +160 -0
- package/runtime/discovery/parser.mjs +40 -0
- package/runtime/discovery/structure.mjs +232 -0
- package/runtime/extensions/contracts.mjs +59 -0
- package/runtime/extensions/frame.mjs +64 -0
- package/runtime/extensions/index.mjs +9 -0
- package/runtime/extensions/manifest.mjs +95 -0
- package/runtime/extensions/packages.mjs +222 -0
- package/runtime/extensions/profiles.mjs +36 -0
- package/runtime/extensions/projection.mjs +130 -0
- package/runtime/extensions/registry.mjs +285 -0
- package/runtime/extensions/scene.mjs +105 -0
- package/runtime/extensions/sdk.d.ts +205 -0
- package/runtime/extensions/sdk.mjs +88 -0
- package/runtime/jev/index.mjs +13 -777
- package/runtime/jev/provider.mjs +101 -0
- package/runtime/jev/questions.mjs +16 -258
- package/runtime/jev/wire.mjs +17 -25
- package/runtime/model/changes.mjs +42 -0
- package/runtime/model/history.mjs +124 -0
- package/runtime/model/index.mjs +2 -0
- package/runtime/model/project-model.mjs +889 -0
- package/runtime/model/records.mjs +239 -0
- package/runtime/pipeline.mjs +127 -48
- package/runtime/platform.mjs +254 -0
- package/runtime/visualizers/blocks.mjs +5 -0
- package/runtime/visualizers/c4.mjs +52 -0
- package/runtime/visualizers/changes.mjs +24 -0
- package/runtime/visualizers/code.mjs +5 -0
- package/runtime/visualizers/index.mjs +23 -0
- package/runtime/visualizers/structure.mjs +120 -0
- package/runtime/visualizers/timeline.mjs +66 -0
- package/runtime/web/app.js +369 -86
- package/runtime/web/extension-frame.js +128 -0
- package/runtime/web/index.html +123 -80
- package/runtime/web/model-client.js +162 -0
- package/runtime/web/platform.js +337 -0
- package/runtime/web/scene.js +111 -0
- package/runtime/web/style.css +152 -142
- package/schemas/graph.schema.json +4 -1
- package/scripts/arguments.mjs +5 -1
- package/scripts/build-packages.mjs +6 -2
- package/scripts/control.mjs +1 -1
- package/scripts/daemon.mjs +2 -1
- package/scripts/extensions.mjs +44 -0
- package/scripts/graphlin.mjs +23 -3
- package/scripts/onboarding.mjs +10 -3
- package/scripts/validate-packages.mjs +54 -8
package/runtime/web/style.css
CHANGED
|
@@ -15,6 +15,51 @@
|
|
|
15
15
|
|
|
16
16
|
* { box-sizing: border-box; }
|
|
17
17
|
[hidden] { display: none !important; }
|
|
18
|
+
.view-context { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; padding: 5px 12px; border-bottom: 1px solid var(--line); font-size: 11px; }
|
|
19
|
+
.view-context label { display: inline-flex; gap: 5px; align-items: center; }
|
|
20
|
+
.view-context select, .view-context button { max-width: 210px; font-size: 11px; min-height: 28px; padding: 3px 7px; color: var(--ink); background: var(--white); border: 1px solid var(--line); border-radius: 5px; }
|
|
21
|
+
#scope-breadcrumbs { display: flex; flex-wrap: wrap; gap: 4px; flex: 1; }
|
|
22
|
+
.view-status, .view-coverage { padding: 4px 12px; font-size: 11px; color: var(--muted); }
|
|
23
|
+
.extension-access { padding: 12px; border-bottom: 1px solid var(--line); background: var(--paper); font-size: 12px; }
|
|
24
|
+
.extension-access p { max-width: 78ch; margin-bottom: 8px; }
|
|
25
|
+
#extension-fields { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; }
|
|
26
|
+
#extension-profiles { display: flex; flex-wrap: wrap; gap: 8px 14px; margin: 8px 0; }
|
|
27
|
+
#analysis-controls { display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: center; }
|
|
28
|
+
.diagram-group .group-frame { fill: var(--paper); fill-opacity: .7; stroke: var(--node-ink); stroke-width: 1.5; }
|
|
29
|
+
.diagram-group[data-change="unknown"] .group-frame, .diagram-group[data-change="discovered"] .group-frame { stroke-dasharray: 5 4; }
|
|
30
|
+
.diagram-group[data-change="modified"] .group-frame { stroke: var(--amber); }
|
|
31
|
+
.diagram-group[data-change="added"] .group-frame { stroke: var(--teal); }
|
|
32
|
+
.diagram-group:focus-visible { outline: none; }
|
|
33
|
+
.diagram-group:focus-visible .group-frame, .diagram-group[aria-pressed="true"] .group-frame { stroke: var(--diagram-focus); stroke-width: 3; }
|
|
34
|
+
.diagram-group[data-change="stale"] .group-frame { stroke-dasharray: 7 4; opacity: .65; }
|
|
35
|
+
.group-heading { fill: var(--ink); font: 600 14px var(--body); }
|
|
36
|
+
.group-summary { fill: var(--muted); font: 11px var(--body); }
|
|
37
|
+
.group-toggle { cursor: pointer; }
|
|
38
|
+
.group-toggle rect { fill: var(--white); stroke: var(--line); }
|
|
39
|
+
.group-toggle text { fill: var(--ink); font: 16px var(--body); }
|
|
40
|
+
.group-toggle:focus-visible { outline: none; }
|
|
41
|
+
.group-toggle:focus-visible rect { stroke: var(--diagram-focus); stroke-width: 3; }
|
|
42
|
+
.diagram-node[data-change="added"] .node-shape { stroke: var(--teal); stroke-width: 3; }
|
|
43
|
+
.diagram-node[data-change="discovered"] .node-shape { stroke-dasharray: 3 3; }
|
|
44
|
+
.diagram-node[data-change="modified"] .node-shape { stroke: var(--amber); stroke-width: 3; }
|
|
45
|
+
.diagram-node[data-change="removed"] { opacity: .6; }
|
|
46
|
+
.custom-view { position: absolute; inset: 0; overflow: auto; background: var(--canvas); }
|
|
47
|
+
.custom-view iframe { width: 100%; height: 100%; border: 0; background: var(--canvas); }
|
|
48
|
+
.timeline-note { padding: 14px 18px; font-size: 12px; color: var(--muted); }
|
|
49
|
+
.timeline-events { padding: 0 18px 20px; margin: 0; list-style: none; }
|
|
50
|
+
.timeline-event { display: grid; grid-template-columns: 85px minmax(95px, .7fr) minmax(180px, 2fr) 90px; gap: 6px 12px; align-items: center; padding: 9px 0; border-top: 1px solid var(--line); font-size: 12px; }
|
|
51
|
+
.timeline-event button { text-align: left; padding: 4px 8px; min-height: 30px; }
|
|
52
|
+
.timeline-lane { overflow-wrap: anywhere; }
|
|
53
|
+
.timeline-attribution { grid-column: 3; color: var(--muted); font-size: 11px; }
|
|
54
|
+
.timeline-outcome { color: var(--muted); }
|
|
55
|
+
.timeline-event[data-outcome="failed"] .timeline-outcome { color: var(--red); }
|
|
56
|
+
.timeline-event[data-outcome="succeeded"] .timeline-outcome { color: var(--teal); }
|
|
57
|
+
@media (max-width: 650px) {
|
|
58
|
+
.timeline-event { grid-template-columns: 75px 1fr; }
|
|
59
|
+
.timeline-event button, .timeline-attribution { grid-column: 2; }
|
|
60
|
+
.view-context { gap: 6px; }
|
|
61
|
+
#scope-breadcrumbs { flex-basis: 100%; }
|
|
62
|
+
}
|
|
18
63
|
body { margin: 0; color: var(--ink); background: var(--paper); font: 14px/1.5 var(--body); }
|
|
19
64
|
button, input, select { font: inherit; }
|
|
20
65
|
button, a, input, select { -webkit-tap-highlight-color: transparent; }
|
|
@@ -24,39 +69,42 @@ button:disabled { opacity: .5; cursor: default; }
|
|
|
24
69
|
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible, summary:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }
|
|
25
70
|
a { color: var(--blue); }
|
|
26
71
|
p, h1, h2, h3 { margin: 0; }
|
|
27
|
-
.page {
|
|
72
|
+
.page { width: 100%; height: 100vh; height: 100dvh; min-height: 620px; display: flex; flex-direction: column; }
|
|
73
|
+
main { flex: 1; min-height: 0; display: flex; flex-direction: column; }
|
|
28
74
|
.skip-link { position: fixed; top: -100px; left: 20px; z-index: 20; padding: 12px 18px; background: var(--white); border: 2px solid var(--blue); border-radius: 6px; }
|
|
29
75
|
.skip-link:focus { top: 12px; }
|
|
30
|
-
.masthead { display: flex; align-items: center;
|
|
31
|
-
.brand { display: inline-flex; align-items: center; gap:
|
|
32
|
-
.brand-mark { width:
|
|
76
|
+
.masthead { display: flex; align-items: center; min-height: 54px; padding: 7px 16px; border-bottom: 1px solid var(--line); gap: 22px; background: var(--white); flex-shrink: 0; }
|
|
77
|
+
.brand { display: inline-flex; align-items: center; gap: 9px; color: var(--ink); font-size: 23px; font-weight: 750; letter-spacing: -1.1px; text-decoration: none; flex-shrink: 0; }
|
|
78
|
+
.brand-mark { width: 22px; height: 22px; border: 2px solid var(--blue); border-radius: 6px; transform: rotate(-9deg); position: relative; }
|
|
33
79
|
.brand-mark::after { content: ""; position: absolute; right: -8px; bottom: -6px; width: 12px; height: 12px; border: 3px solid var(--paper); border-radius: 50%; background: var(--teal); }
|
|
34
|
-
.connection { display: flex; align-items: center; gap:
|
|
80
|
+
.connection { display: flex; align-items: center; gap: 7px; color: var(--muted); font-size: 11px; margin-left: auto; max-width: 250px; }
|
|
81
|
+
.update-indicator { flex-shrink: 0; min-height: 28px; padding: 3px 8px; font-size: 10px; color: var(--teal); border-color: var(--teal); }
|
|
35
82
|
.connection-dot, .status-dot { display: inline-block; flex: 0 0 7px; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
|
|
36
83
|
.connection[data-state="connected"] .connection-dot, .status-dot[data-state="ready"] { background: var(--teal); }
|
|
37
84
|
.connection[data-state="reconnecting"] .connection-dot, .status-dot[data-state="waiting"] { background: var(--amber); }
|
|
38
85
|
.connection[data-state="error"] .connection-dot, .connection[data-state="auth"] .connection-dot, .status-dot[data-state="error"] { background: var(--red); }
|
|
39
86
|
.text-button { background: transparent; border-color: transparent; padding: 4px 6px; min-height: 32px; color: var(--blue); font-size: 12px; }
|
|
40
|
-
.intro { padding: 25px 0 24px; display: flex; align-items: end; justify-content: space-between; gap: 22px; }
|
|
41
87
|
h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650; line-height: 1.2; }
|
|
42
|
-
.
|
|
43
|
-
.intro .project-label { font-size: 12px; max-width: 250px; text-align: right; overflow-wrap: anywhere; }
|
|
44
|
-
.notice { padding: 11px 16px; margin-bottom: 14px; border-radius: 7px; font-size: 13px; }
|
|
88
|
+
.notice { flex-shrink: 0; padding: 6px 16px; font-size: 11px; max-height: 20dvh; overflow: auto; }
|
|
45
89
|
.demo-notice { display: flex; gap: 12px; color: #744807; background: #fff7e6; border: 1px solid #e6cb96; }
|
|
46
90
|
.demo-notice strong { white-space: nowrap; }
|
|
47
91
|
.error-notice { color: #85223a; background: #fff1f4; border: 1px solid #e8b8c3; }
|
|
48
|
-
.workspace {
|
|
49
|
-
.workspace-toolbar {
|
|
50
|
-
.session-picker { display: flex; align-items: center; gap:
|
|
51
|
-
.session-picker select { color: var(--ink); font-size:
|
|
52
|
-
.session-actions { display: flex; flex-wrap: wrap; gap:
|
|
53
|
-
.
|
|
92
|
+
.workspace { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--white); }
|
|
93
|
+
.workspace-toolbar { padding: 6px 12px; display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; border-bottom: 1px solid var(--line); flex-shrink: 0; }
|
|
94
|
+
.session-picker { display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--muted); min-width: 0; }
|
|
95
|
+
.session-picker select { color: var(--ink); font-size: 11px; font-weight: 600; border: 1px solid var(--line); border-radius: 5px; padding: 5px 22px 5px 8px; background: var(--paper); max-width: min(240px, 30vw); min-width: 100px; min-height: 32px; }
|
|
96
|
+
.session-actions { display: flex; flex-wrap: wrap; gap: 5px; margin-left: auto; font-size: 11px; }
|
|
97
|
+
.session-actions button, .panel-controls button { min-height: 32px; padding: 5px 9px; font-size: 11px; }
|
|
98
|
+
.panel-controls { display: flex; gap: 4px; }
|
|
99
|
+
.panel-controls button[aria-expanded="true"] { background: var(--soft); border-color: var(--blue); color: var(--blue); }
|
|
100
|
+
.status-strip { display: flex; flex-direction: column; gap: 9px; padding: 14px 17px; font-size: 11px; border-bottom: 1px solid var(--line); }
|
|
54
101
|
.classification-status { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
|
|
55
102
|
.classification-status strong { font-weight: 650; }
|
|
56
103
|
#capture-note { color: var(--muted); }
|
|
57
|
-
.coverage-status { display: flex; gap: 4px
|
|
104
|
+
.coverage-status { display: flex; gap: 4px 12px; color: var(--muted); flex-wrap: wrap; }
|
|
58
105
|
#coverage-label { max-width: 67ch; }
|
|
59
|
-
.workspace-body { display: grid; grid-template-columns: minmax(0, 1fr)
|
|
106
|
+
.workspace-body { position: relative; flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr); align-items: stretch; }
|
|
107
|
+
.workspace-body[data-details-open="true"] { grid-template-columns: minmax(0, 1fr) 340px; }
|
|
60
108
|
.sidebar-theme,
|
|
61
109
|
.drawing {
|
|
62
110
|
--canvas: #fbfaf7; --ink: #293340; --muted: #4b5765; --node-ink: #343d49;
|
|
@@ -67,7 +115,7 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
67
115
|
--role-queue: #fae8bd; --role-external: #f4dbe3; --role-module: #e3e7ed;
|
|
68
116
|
--role-function: #d6edf2; --role-class: #dedaf3; --role-interface: #dde3fa;
|
|
69
117
|
--role-event: #f8ddc7; --role-configuration: #e6edce; --role-package: #eee0d1;
|
|
70
|
-
color-scheme: light; color: var(--ink); min-width: 0; display: flex; flex-direction: column;
|
|
118
|
+
color-scheme: light; color: var(--ink); min-width: 0; min-height: 0; display: flex; flex-direction: column;
|
|
71
119
|
background-color: var(--canvas); background-image: radial-gradient(var(--diagram-grid) .65px, transparent .65px); background-size: 18px 18px;
|
|
72
120
|
}
|
|
73
121
|
.sidebar-theme[data-theme="ocean"],
|
|
@@ -161,35 +209,49 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
161
209
|
.drawing [data-kind="event"], .sidebar-theme [data-kind="event"] { --node-fill: var(--role-event); }
|
|
162
210
|
.drawing [data-kind="configuration"], .sidebar-theme [data-kind="configuration"] { --node-fill: var(--role-configuration); }
|
|
163
211
|
.drawing [data-kind="package"], .sidebar-theme [data-kind="package"] { --node-fill: var(--role-package); }
|
|
212
|
+
.drawing [data-kind="method"] { --node-fill: var(--role-function); }
|
|
213
|
+
.drawing [data-kind="enum"] { --node-fill: var(--role-class); }
|
|
214
|
+
.drawing [data-kind="type_alias"] { --node-fill: var(--role-interface); }
|
|
215
|
+
.drawing [data-kind="namespace"], .drawing [data-kind="directory"], .drawing [data-kind="project"] { --node-fill: var(--role-package); }
|
|
164
216
|
.drawing button:hover:not(:disabled) { background: var(--soft); border-color: var(--diagram-focus); }
|
|
165
217
|
.drawing :is(button, input, select, summary):focus-visible { outline-color: var(--diagram-focus); }
|
|
166
|
-
.drawing-toolbar { display: flex;
|
|
167
|
-
.drawing-heading { display: flex; align-items: baseline; gap:
|
|
218
|
+
.drawing-toolbar { display: flex; flex-wrap: wrap; align-items: center; padding: 6px 12px; gap: 6px 18px; background: var(--canvas); border-bottom: 1px solid var(--line); flex-shrink: 0; }
|
|
219
|
+
.drawing-heading { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
|
|
168
220
|
.drawing-heading h2 { font-size: 13px; font-weight: 600; }
|
|
169
221
|
#revision { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
170
|
-
.zoom-controls { display: flex; gap: 3px; align-items: center; background: var(--canvas); flex-shrink: 0; }
|
|
222
|
+
.zoom-controls { display: flex; gap: 3px; align-items: center; background: var(--canvas); flex-shrink: 0; margin-left: auto; }
|
|
171
223
|
.zoom-controls button { border: 0; background: transparent; min-width: 31px; min-height: 32px; padding: 2px 8px; font-size: 17px; }
|
|
172
224
|
.zoom-controls #fit { border: 1px solid var(--line); font-size: 11px; margin-left: 5px; min-width: 39px; }
|
|
173
|
-
.layout-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap:
|
|
174
|
-
.project-details {
|
|
175
|
-
.project-details dl { display: flex; flex-wrap: wrap; gap:
|
|
176
|
-
.project-details dl > div { min-width: 0; }
|
|
177
|
-
.project-details dt { color: var(--muted); font-size: 10px;
|
|
225
|
+
.layout-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: 11px; }
|
|
226
|
+
.project-details { min-width: 0; flex: 1; font-size: 11px; }
|
|
227
|
+
.project-details dl { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 16px; margin: 0; }
|
|
228
|
+
.project-details dl > div { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
|
|
229
|
+
.project-details dt { color: var(--muted); font-size: 10px; }
|
|
178
230
|
.project-details dd { margin: 0; overflow-wrap: anywhere; }
|
|
179
|
-
.project-details .project-path { flex: 1 1
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
.project-details
|
|
183
|
-
.
|
|
184
|
-
.
|
|
185
|
-
.
|
|
186
|
-
.
|
|
231
|
+
.project-details .project-path { flex: 1 1 160px; }
|
|
232
|
+
#project-path { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
233
|
+
#project-branch { max-width: 22ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
234
|
+
.project-details .project-label { font-size: 11px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
235
|
+
.version-details { padding: 12px 17px; font-size: 11px; color: var(--muted); border-bottom: 1px solid var(--line); }
|
|
236
|
+
.version-details details { margin-top: 8px; }
|
|
237
|
+
.version-details summary { cursor: pointer; font-weight: 600; }
|
|
238
|
+
.version-details pre { white-space: pre-wrap; overflow-wrap: anywhere; padding: 10px; background: var(--paper); }
|
|
239
|
+
.version-details button { min-height: 32px; font-size: 11px; }
|
|
240
|
+
.diagram-search-bar { display: flex; align-items: center; gap: 6px; flex: 0 1 360px; min-width: 200px; font-size: 11px; color: var(--muted); }
|
|
241
|
+
.diagram-search-bar input { flex: 1 1 130px; width: 100%; min-width: 80px; min-height: 32px; padding: 5px 9px; border: 1px solid var(--line); border-radius: 5px; background: var(--white); color: var(--ink); }
|
|
187
242
|
.diagram-search-bar input::placeholder { color: var(--muted); opacity: 1; }
|
|
188
|
-
.diagram-search-bar button { min-height:
|
|
243
|
+
.diagram-search-bar button { min-height: 32px; font-size: 11px; padding: 5px 7px; white-space: nowrap; }
|
|
244
|
+
#diagram-search-status { font-size: 10px; min-width: 72px; max-width: 140px; line-height: 1.3; }
|
|
245
|
+
.filter-toolbar { display: flex; align-items: center; gap: 12px; padding: 5px 12px; background: var(--canvas); border-bottom: 1px solid var(--line); flex-shrink: 0; }
|
|
246
|
+
.node-type-toolbar { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1; }
|
|
247
|
+
.node-type-toolbar button { font-size: 10px; min-height: 30px; padding: 4px 8px; white-space: nowrap; background: var(--white); flex-shrink: 0; }
|
|
248
|
+
#node-type-filters { display: flex; align-items: center; gap: 5px; min-width: 0; overflow-x: auto; padding: 4px; scrollbar-width: thin; }
|
|
249
|
+
#node-type-filters button[aria-pressed="true"] { background: var(--node-fill, var(--soft)); border-color: var(--blue); color: var(--ink); }
|
|
250
|
+
#node-type-filters button[aria-pressed="false"] { border-style: dashed; color: var(--muted); }
|
|
189
251
|
#diagram-search-status:empty { display: none; }
|
|
190
252
|
.layout-toolbar label { display: flex; align-items: center; gap: 8px; color: var(--muted); }
|
|
191
|
-
.layout-toolbar select, .shape-picker select { color: var(--ink); background: var(--white); border: 1px solid var(--line); border-radius: 5px; padding:
|
|
192
|
-
.layout-toolbar button { font-size: 11px; min-height:
|
|
253
|
+
.layout-toolbar select, .shape-picker select { color: var(--ink); background: var(--white); border: 1px solid var(--line); border-radius: 5px; padding: 5px 23px 5px 8px; font: inherit; min-height: 32px; }
|
|
254
|
+
.layout-toolbar button { font-size: 11px; min-height: 32px; padding: 5px 9px; }
|
|
193
255
|
.layout-toolbar .auto-arrange { color: var(--ink); white-space: nowrap; }
|
|
194
256
|
.theme-picker { display: flex; align-items: center; gap: 8px; }
|
|
195
257
|
.theme-preview { display: inline-flex; align-items: center; padding: 2px; }
|
|
@@ -198,14 +260,14 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
198
260
|
.theme-preview i:nth-child(3) { transform: rotate(-3deg); background: var(--role-queue); }
|
|
199
261
|
.theme-preview i:nth-child(4) { transform: rotate(7deg); background: var(--role-datastore); }
|
|
200
262
|
.auto-arrange input { width: 15px; height: 15px; margin: 0; accent-color: var(--blue); }
|
|
201
|
-
|
|
263
|
+
|
|
202
264
|
#zoom-level { font-size: 11px; color: var(--muted); min-width: 39px; text-align: center; font-variant-numeric: tabular-nums; }
|
|
203
|
-
.diagram-stage { position: relative; min-height:
|
|
265
|
+
.diagram-stage { position: relative; min-height: 180px; flex: 1 1 0; overflow: hidden; }
|
|
204
266
|
#architecture { display: block; height: 100%; width: 100%; touch-action: pan-y; }
|
|
205
267
|
#architecture:focus-visible { outline: 2px solid var(--diagram-focus); outline-offset: -5px; }
|
|
206
268
|
#architecture.is-pannable { cursor: grab; touch-action: none; }
|
|
207
269
|
#architecture.is-panning { cursor: grabbing; }
|
|
208
|
-
.empty-canvas { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding:
|
|
270
|
+
.empty-canvas { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: safe center; text-align: center; padding: 24px; overflow: auto; pointer-events: none; }
|
|
209
271
|
.empty-canvas h3 { font-size: 24px; letter-spacing: -.6px; font-weight: 600; margin: 20px 0 9px; }
|
|
210
272
|
.empty-canvas p { color: var(--muted); max-width: 46ch; font-size: 13px; }
|
|
211
273
|
.orientation { pointer-events: auto; max-width: 46ch; margin-top: 18px; }
|
|
@@ -225,14 +287,14 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
225
287
|
.empty-map i { width: 41px; height: 30px; border: 1.5px dashed #7999c3; border-radius: 6px; background: var(--paper); }
|
|
226
288
|
.empty-map i:last-child { height: 38px; width: 31px; border-radius: 50% / 14%; }
|
|
227
289
|
.empty-map span { width: 40px; border-top: 1.5px dashed #7999c3; }
|
|
228
|
-
.drawing-footer { display: flex; justify-content: space-between; gap: 16px; padding:
|
|
290
|
+
.drawing-footer { display: flex; justify-content: space-between; gap: 5px 16px; padding: 6px 12px 2px; font-size: 10px; color: var(--muted); flex-wrap: wrap; flex-shrink: 0; background: var(--canvas); }
|
|
229
291
|
.legend { display: flex; flex-wrap: wrap; gap: 17px; }
|
|
230
292
|
.legend span { display: flex; align-items: center; gap: 6px; }
|
|
231
293
|
.legend i { width: 15px; height: 10px; display: inline-block; border: 1.5px solid var(--blue); border-radius: 3px; background: var(--white); }
|
|
232
294
|
.legend .proposed { border-color: var(--amber); border-style: dashed; background: var(--paper); }
|
|
233
295
|
.legend .stale { border-color: var(--diagram-stale); border-style: dotted; background: var(--paper); }
|
|
234
|
-
.diagram-note { color: var(--muted); font-size: 10px; padding:
|
|
235
|
-
.shape-key { color: var(--muted); font-size:
|
|
296
|
+
.diagram-note { color: var(--muted); font-size: 10px; padding: 0 12px 5px; background: var(--canvas); flex-shrink: 0; }
|
|
297
|
+
.shape-key { color: var(--muted); font-size: 11px; padding: 10px 17px; border-bottom: 1px solid var(--line); }
|
|
236
298
|
.shape-key summary { cursor: pointer; width: fit-content; padding: 3px 0; }
|
|
237
299
|
#shape-key-items { display: grid; grid-template-columns: repeat(auto-fit, minmax(115px, 1fr)); gap: 7px 12px; margin: 9px 0; }
|
|
238
300
|
.shape-key-item { display: flex; align-items: center; gap: 7px; }
|
|
@@ -307,7 +369,10 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
307
369
|
.arrow-observed { fill: var(--diagram-edge); }
|
|
308
370
|
.arrow-proposed { fill: var(--amber); }
|
|
309
371
|
.arrow-stale { fill: var(--diagram-stale); }
|
|
310
|
-
.live-sidebar { min-width: 0; max-height:
|
|
372
|
+
.live-sidebar { min-width: 0; min-height: 0; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; border-left: 1px solid var(--line); background: var(--white); }
|
|
373
|
+
.details-heading { position: sticky; top: 0; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 17px; background: var(--white); border-bottom: 1px solid var(--line); }
|
|
374
|
+
.details-heading h2 { font-size: 13px; }
|
|
375
|
+
.details-heading button { font-size: 11px; min-height: 30px; padding: 4px 8px; }
|
|
311
376
|
.sidebar-hooks { padding: 14px 17px 12px; border-bottom: 1px solid var(--line); }
|
|
312
377
|
.sidebar-hooks > summary { display: flex; align-items: center; gap: 10px; min-height: 30px; cursor: pointer; list-style: none; }
|
|
313
378
|
.sidebar-hooks > summary::-webkit-details-marker { display: none; }
|
|
@@ -393,7 +458,7 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
393
458
|
.source-reference summary { color: var(--blue); cursor: pointer; font-size: 11px; margin-top: 8px; }
|
|
394
459
|
.source-reference pre { font: 11px/1.6 ui-monospace, "SFMono-Regular", Consolas, monospace; white-space: pre-wrap; overflow-wrap: anywhere; margin: 9px 0 0; border-radius: 4px; padding: 9px; background: var(--paper); max-height: 220px; overflow: auto; tab-size: 2; }
|
|
395
460
|
.related-event { width: 100%; padding: 6px 0; text-align: left; font-size: 11px; color: var(--blue); background: none; border: 0; font-weight: 500; }
|
|
396
|
-
.playback { border-top: 1px solid var(--line); display: grid; grid-template-columns: auto minmax(100px, 1fr) minmax(190px, 290px); align-items: center; gap:
|
|
461
|
+
.playback { border-top: 1px solid var(--line); display: grid; grid-template-columns: auto minmax(100px, 1fr) minmax(190px, 290px); align-items: center; gap: 14px; padding: 8px 12px; flex-shrink: 0; max-height: 25dvh; overflow: auto; }
|
|
397
462
|
.mode-buttons { display: flex; background: var(--paper); border: 1px solid var(--line); border-radius: 7px; padding: 2px; }
|
|
398
463
|
.mode-buttons button { border: 0; background: transparent; color: var(--muted); min-height: 31px; font-size: 12px; border-radius: 4px; }
|
|
399
464
|
.mode-buttons button[aria-pressed="true"] { color: var(--blue); background: var(--white); box-shadow: 0 1px 4px #16324e12; }
|
|
@@ -401,9 +466,10 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
401
466
|
.scrubber input { accent-color: var(--blue); min-width: 20px; width: 100%; cursor: pointer; }
|
|
402
467
|
.scrubber output { font-size: 11px; white-space: nowrap; min-width: 60px; color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
403
468
|
#replay-note { font-size: 10px; color: var(--muted); text-align: right; }
|
|
404
|
-
.activity-section { padding-top:
|
|
405
|
-
|
|
406
|
-
.activity-heading
|
|
469
|
+
.activity-section { height: min(220px, 28dvh); min-height: 110px; flex-shrink: 0; display: flex; flex-direction: column; padding: 10px 16px 0; border-top: 1px solid var(--line); background: var(--white); }
|
|
470
|
+
#activity-content { min-height: 0; overflow: auto; overscroll-behavior: contain; }
|
|
471
|
+
.activity-heading { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px 12px; margin-bottom: 7px; flex-shrink: 0; }
|
|
472
|
+
.activity-heading h2 { font-size: 13px; font-weight: 600; }
|
|
407
473
|
.activity-heading p { font-size: 11px; color: var(--muted); margin-top: 3px; }
|
|
408
474
|
#activity-count { color: var(--muted); font-size: 11px; }
|
|
409
475
|
.activity-list { list-style: none; padding: 0; margin: 0; border-top: 1px solid var(--line); max-height: 330px; overflow-y: auto; scrollbar-width: thin; }
|
|
@@ -419,7 +485,7 @@ h1 { font-size: clamp(27px, 2.3vw, 36px); letter-spacing: -1px; font-weight: 650
|
|
|
419
485
|
.event-state { color: var(--muted); text-align: right; font-size: 11px; }
|
|
420
486
|
.activity-empty { padding: 25px 22px; color: var(--muted); font-size: 12px; border: 1px dashed #bbcee6; border-radius: 8px; }
|
|
421
487
|
.activity-item.is-focused { background: #eaf0fc; }
|
|
422
|
-
footer {
|
|
488
|
+
footer { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 12px; padding: 3px 12px; border-top: 1px solid var(--line); font-size: 9px; color: var(--muted); flex-shrink: 0; }
|
|
423
489
|
footer span { margin: 0 8px; color: #91a7c3; }
|
|
424
490
|
.toast { position: fixed; bottom: 25px; left: 50%; transform: translateX(-50%); background: var(--ink); color: var(--white); padding: 12px 20px; border-radius: 8px; font-size: 12px; z-index: 10; max-width: calc(100vw - 32px); box-shadow: 0 6px 30px #16324e20; }
|
|
425
491
|
.connection-dialog { width: min(760px, calc(100% - 32px)); max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px); margin: auto; padding: 25px 28px; border: 1px solid var(--line); border-radius: 13px; background: var(--white); color: var(--ink); box-shadow: 0 24px 100px #16324e30; overflow-y: auto; }
|
|
@@ -491,54 +557,41 @@ footer span { margin: 0 8px; color: #91a7c3; }
|
|
|
491
557
|
.diagnostics-log-path { color: var(--muted); font-size: 11px; line-height: 1.6; overflow-wrap: anywhere; margin: 8px 0 0; }
|
|
492
558
|
.screen-reader { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
|
|
493
559
|
|
|
494
|
-
@media (min-width: 1450px) {
|
|
495
|
-
.workspace-body { grid-template-columns: minmax(0, 1fr) 345px; }
|
|
496
|
-
.inspector { padding: 19px 25px; }
|
|
497
|
-
}
|
|
498
560
|
@media (max-width: 1100px) {
|
|
499
|
-
.
|
|
500
|
-
.
|
|
501
|
-
.
|
|
502
|
-
.
|
|
503
|
-
.
|
|
504
|
-
.inspector { padding: 17px; }
|
|
505
|
-
.playback { gap: 16px; grid-template-columns: auto 1fr; }
|
|
506
|
-
#replay-note { grid-column: 2; margin-top: -9px; text-align: left; }
|
|
507
|
-
.drawing-toolbar { padding: 15px 15px 0; }
|
|
508
|
-
.layout-toolbar { padding-right: 15px; padding-left: 15px; }
|
|
509
|
-
.diagram-search-bar { padding-right: 15px; padding-left: 15px; }
|
|
510
|
-
.drawing-heading { gap: 3px 10px; }
|
|
511
|
-
.drawing-footer { padding-right: 15px; padding-left: 15px; }
|
|
512
|
-
.diagram-note { padding-left: 15px; }
|
|
513
|
-
}
|
|
514
|
-
@media (max-width: 1000px) {
|
|
515
|
-
.workspace-body { grid-template-columns: 1fr; }
|
|
516
|
-
.live-sidebar { border-left: 0; border-top: 1px solid var(--line); max-height: 640px; }
|
|
517
|
-
.inspector { padding: 17px 21px; }
|
|
518
|
-
.change-tiles { grid-template-columns: repeat(8, minmax(0, 1fr)); }
|
|
519
|
-
.inspector-header { margin-bottom: 8px; }
|
|
520
|
-
.inspector-empty { padding-top: 5px; }
|
|
521
|
-
.inspector-glyph { display: none; }
|
|
522
|
-
.inspector-empty h3 { font-size: 18px; margin-bottom: 6px; }
|
|
523
|
-
.inspector-empty p { max-width: 65ch; margin-bottom: 7px; }
|
|
524
|
-
.inspector-empty .inspector-hint { margin-top: 5px; }
|
|
561
|
+
.drawing-heading { flex: 1; }
|
|
562
|
+
.layout-toolbar { order: 1; width: 100%; }
|
|
563
|
+
.theme-preview { display: none; }
|
|
564
|
+
.session-actions { gap: 4px; }
|
|
565
|
+
.workspace-body[data-details-open="true"] { grid-template-columns: minmax(0, 1fr) 310px; }
|
|
525
566
|
}
|
|
526
567
|
@media (max-width: 800px) {
|
|
527
|
-
.page {
|
|
528
|
-
.masthead {
|
|
529
|
-
.
|
|
530
|
-
.
|
|
531
|
-
.
|
|
532
|
-
.
|
|
533
|
-
.
|
|
534
|
-
.
|
|
535
|
-
.session-
|
|
536
|
-
.
|
|
537
|
-
.
|
|
568
|
+
.page { height: auto; min-height: 100dvh; }
|
|
569
|
+
.masthead { flex-wrap: wrap; gap: 6px 16px; padding: 8px 12px; }
|
|
570
|
+
.project-details { flex-basis: 100%; order: 1; }
|
|
571
|
+
.project-details .project-label { display: inline; margin-right: 12px; }
|
|
572
|
+
.project-details dl { gap: 3px 12px; }
|
|
573
|
+
.connection { font-size: 10px; max-width: 60%; }
|
|
574
|
+
.session-picker { flex: 1; }
|
|
575
|
+
.session-picker select { max-width: 100%; width: 100%; min-width: 0; }
|
|
576
|
+
.session-actions { width: 100%; margin-left: 0; }
|
|
577
|
+
.workspace-body[data-details-open="true"] { grid-template-columns: minmax(0, 1fr); }
|
|
578
|
+
.live-sidebar { position: absolute; top: 0; bottom: 0; right: 0; width: min(360px, 100%); z-index: 4; box-shadow: -6px 0 24px #16324e18; }
|
|
579
|
+
.layout-toolbar { flex-wrap: nowrap; overflow-x: auto; padding: 4px; scrollbar-width: thin; }
|
|
580
|
+
.layout-toolbar > * { flex-shrink: 0; }
|
|
581
|
+
.filter-toolbar { flex-wrap: wrap; gap: 2px; }
|
|
582
|
+
.diagram-search-bar { flex: 1 1 100%; }
|
|
583
|
+
.node-type-toolbar { flex-basis: 100%; }
|
|
584
|
+
.diagram-stage { min-height: max(320px, calc(100dvh - 335px)); }
|
|
585
|
+
.empty-canvas { padding: 20px; }
|
|
586
|
+
.empty-canvas h3 { font-size: 21px; }
|
|
587
|
+
.empty-canvas p { font-size: 12px; }
|
|
588
|
+
.playback { gap: 5px 12px; grid-template-columns: auto minmax(0, 1fr); }
|
|
589
|
+
#replay-note { grid-column: 1 / -1; text-align: left; }
|
|
538
590
|
.event-detail { display: none; }
|
|
591
|
+
.activity-row { grid-template-columns: 57px 5px minmax(60px, 1fr) 68px; gap: 7px; padding: 12px 3px; font-size: 11px; }
|
|
592
|
+
.legend { gap: 5px 12px; }
|
|
539
593
|
}
|
|
540
594
|
@media (max-width: 550px) {
|
|
541
|
-
.change-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
542
595
|
.diagnostics-dialog { padding: 19px 15px; width: calc(100% - 20px); max-height: calc(100dvh - 24px); }
|
|
543
596
|
.diagnostics-header h2 { font-size: 21px; }
|
|
544
597
|
.diagnostics-filters { grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
|
|
@@ -552,59 +605,16 @@ footer span { margin: 0 8px; color: #91a7c3; }
|
|
|
552
605
|
.connection-steps { padding-left: 18px; }
|
|
553
606
|
.connection-steps pre { padding: 10px; font-size: 11px; }
|
|
554
607
|
.connection-step-heading button { min-height: 40px; }
|
|
555
|
-
.
|
|
556
|
-
.
|
|
557
|
-
.
|
|
558
|
-
.
|
|
559
|
-
#connection-label { max-width: 145px; text-align: right; }
|
|
560
|
-
.connection .text-button { min-height: 26px; padding: 0 2px; font-size: 10px; }
|
|
561
|
-
.intro { display: block; padding: 22px 2px 18px; }
|
|
562
|
-
h1 { font-size: 27px; letter-spacing: -.8px; }
|
|
563
|
-
.intro p { font-size: 12px; max-width: 38ch; }
|
|
564
|
-
.intro .project-label { max-width: none; text-align: left; font-size: 10px; padding-top: 3px; }
|
|
565
|
-
.demo-notice { flex-direction: column; gap: 3px; font-size: 11px; padding: 11px 13px; }
|
|
566
|
-
.workspace { border-radius: 9px; }
|
|
567
|
-
.workspace-toolbar { flex-wrap: wrap; gap: 10px; padding: 12px; }
|
|
568
|
-
.session-picker { width: 100%; }
|
|
569
|
-
.session-picker select { flex: 1; max-width: none; min-width: 0; min-height: 43px; }
|
|
570
|
-
.session-actions { width: 100%; }
|
|
571
|
-
.session-actions button { flex: 1; min-height: 43px; }
|
|
572
|
-
.status-strip { flex-direction: column; align-items: start; gap: 8px; padding: 11px 13px; }
|
|
573
|
-
.classification-status { max-width: none; font-size: 10px; gap: 6px; }
|
|
574
|
-
#capture-note { flex-basis: 100%; padding-left: 13px; }
|
|
575
|
-
.coverage-status { flex-direction: row; text-align: left; gap: 5px 14px; font-size: 10px; max-width: none; }
|
|
576
|
-
.drawing-toolbar { padding: 10px 10px 0; gap: 7px; align-items: start; }
|
|
577
|
-
.layout-toolbar { padding: 10px 12px 3px; gap: 9px; }
|
|
578
|
-
.diagram-search-bar { padding: 10px 12px 3px; gap: 8px; }
|
|
579
|
-
.layout-toolbar select, .layout-toolbar button { min-height: 40px; }
|
|
580
|
-
.auto-arrange { min-height: 30px; }
|
|
581
|
-
.shape-key { padding-right: 12px; padding-left: 12px; }
|
|
582
|
-
.drawing-heading { display: flex; flex-direction: column; padding-top: 8px; gap: 3px; }
|
|
583
|
-
.drawing-heading h2 { font-size: 11px; }
|
|
608
|
+
.brand { font-size: 22px; }
|
|
609
|
+
.drawing-toolbar { gap: 3px 7px; }
|
|
610
|
+
.drawing-heading { gap: 3px 8px; }
|
|
611
|
+
.drawing-heading h2 { font-size: 12px; }
|
|
584
612
|
#revision { font-size: 10px; }
|
|
585
|
-
.
|
|
586
|
-
.
|
|
587
|
-
.
|
|
588
|
-
|
|
589
|
-
.diagram-stage { height: 350px; min-height: 350px; }
|
|
590
|
-
.empty-canvas { padding: 24px; }
|
|
591
|
-
.empty-canvas h3 { font-size: 21px; }
|
|
592
|
-
.empty-canvas p { font-size: 12px; }
|
|
593
|
-
.legend { gap: 7px 13px; }
|
|
594
|
-
.drawing-footer { padding: 9px 12px 5px; gap: 8px; font-size: 9px; }
|
|
595
|
-
.diagram-note { padding: 0 12px 12px; font-size: 9px; }
|
|
596
|
-
.inspector { padding: 13px 16px; }
|
|
597
|
-
.playback { padding: 12px; gap: 9px; grid-template-columns: 1fr; }
|
|
598
|
-
.mode-buttons { justify-self: start; }
|
|
599
|
-
.mode-buttons button { min-height: 40px; min-width: 63px; }
|
|
600
|
-
.scrubber input { min-height: 35px; }
|
|
601
|
-
#replay-note { grid-column: 1; margin-top: -3px; }
|
|
602
|
-
.activity-heading h2 { font-size: 16px; }
|
|
603
|
-
.activity-heading p { font-size: 10px; max-width: 30ch; }
|
|
604
|
-
.activity-row { grid-template-columns: 57px 5px minmax(60px, 1fr) 68px; gap: 7px; padding: 12px 3px; font-size: 11px; }
|
|
613
|
+
.layout-toolbar label { gap: 5px; }
|
|
614
|
+
.drawing-footer { font-size: 9px; }
|
|
615
|
+
.diagram-note { font-size: 9px; }
|
|
616
|
+
.activity-heading p { font-size: 10px; }
|
|
605
617
|
.activity-row time, .event-state { font-size: 9px; }
|
|
606
|
-
.activity-empty { padding: 18px; font-size: 11px; }
|
|
607
|
-
footer { flex-direction: column; gap: 5px; margin-top: 22px; }
|
|
608
618
|
}
|
|
609
619
|
@media (prefers-reduced-motion: reduce) {
|
|
610
620
|
*, *::before, *::after { scroll-behavior: auto !important; animation: none !important; transition: none !important; }
|
package/scripts/arguments.mjs
CHANGED
|
@@ -21,8 +21,12 @@ export function parseArguments(args, { worker = false } = {}) {
|
|
|
21
21
|
const value = args.shift();
|
|
22
22
|
if (!/^\d{1,5}$/.test(value ?? '') || Number(value) > 65535) throw new Error('invalid_port');
|
|
23
23
|
values.port = Number(value);
|
|
24
|
+
} else if (argument === '--local-source') {
|
|
25
|
+
if (seen.has('--allow-source') || seen.has('--no-source')) throw new Error('conflicting_arguments');
|
|
26
|
+
values.allowSource = false;
|
|
27
|
+
values.localSource = true;
|
|
24
28
|
} else if (argument === '--allow-source' || argument === '--no-source' && !worker) {
|
|
25
|
-
if (seen.has(argument === '--allow-source' ? '--no-source' : '--allow-source')) throw new Error('conflicting_arguments');
|
|
29
|
+
if (seen.has('--local-source') || seen.has(argument === '--allow-source' ? '--no-source' : '--allow-source')) throw new Error('conflicting_arguments');
|
|
26
30
|
values.allowSource = argument === '--allow-source';
|
|
27
31
|
}
|
|
28
32
|
else if (argument === '--persist-evidence') values.persistEvidence = true;
|
|
@@ -7,6 +7,7 @@ import { publicPackageFiles, validatePackage } from './validate-packages.mjs';
|
|
|
7
7
|
|
|
8
8
|
const SOURCE = fileURLToPath(new URL('../', import.meta.url));
|
|
9
9
|
const SOURCE_DIRECTORIES = ['.claude-plugin', '.codex-plugin', 'skills', 'scripts', 'runtime', 'schemas', 'adapters'];
|
|
10
|
+
const PROTECTED_DIRECTORIES = [...SOURCE_DIRECTORIES, 'docs', 'node_modules'];
|
|
10
11
|
|
|
11
12
|
async function assertDestination(destination, { directory = false } = {}) {
|
|
12
13
|
const absolute = path.resolve(destination), root = path.parse(absolute).root;
|
|
@@ -57,7 +58,7 @@ async function copy(source, destination) {
|
|
|
57
58
|
export async function buildPackages({ outputDir = path.join(SOURCE, 'dist'), sourceDir = SOURCE } = {}) {
|
|
58
59
|
const source = path.resolve(sourceDir), output = path.resolve(outputDir);
|
|
59
60
|
if (output === source || source.startsWith(`${output}${path.sep}`)) throw new Error('unsafe_output_directory');
|
|
60
|
-
if (
|
|
61
|
+
if (PROTECTED_DIRECTORIES.some(file => output === path.join(source, file) || output.startsWith(`${path.join(source, file)}${path.sep}`))) {
|
|
61
62
|
throw new Error('unsafe_output_directory');
|
|
62
63
|
}
|
|
63
64
|
// Preflight every output before replacing even the first generated profile.
|
|
@@ -92,6 +93,9 @@ export async function buildPackages({ outputDir = path.join(SOURCE, 'dist'), sou
|
|
|
92
93
|
await mkdir(temporary);
|
|
93
94
|
try {
|
|
94
95
|
const profileFiles = files.filter(file => profile === 'claude' || file !== '.claude-plugin/plugin.json');
|
|
96
|
+
// publicPackageFiles includes every reviewed file of the full pinned
|
|
97
|
+
// parser under Graphlin's own node_modules. Never resolve a hoisted or
|
|
98
|
+
// inspected-project dependency, and never copy an arbitrary dependency tree.
|
|
95
99
|
for (const file of profileFiles) await copy(path.join(source, file), path.join(temporary, file));
|
|
96
100
|
const metadata = JSON.parse(await readFile(path.join(temporary, 'package.json'), 'utf8'));
|
|
97
101
|
metadata.files = metadata.files.filter(file => profileFiles.includes(file.slice(2)));
|
|
@@ -114,7 +118,7 @@ export async function buildPackages({ outputDir = path.join(SOURCE, 'dist'), sou
|
|
|
114
118
|
await chmod(path.join(temporary, 'scripts', file), 0o755);
|
|
115
119
|
}
|
|
116
120
|
await writeFile(path.join(temporary, 'PACKAGE-NOTES.md'),
|
|
117
|
-
`# Graphlin ${profile} package\n\nNode.js 22.14+; macOS/Linux. Self-contained
|
|
121
|
+
`# Graphlin ${profile} package\n\nNode.js 22.14+; macOS/Linux. Self-contained runtime and parser bundle; no dependency install.\n` +
|
|
118
122
|
'Run scripts/graphlin.mjs --help for local controls. This package does not install itself.\n' +
|
|
119
123
|
'Hook activation/trust has not been certified. Kiro is inactive and experimental.\n' +
|
|
120
124
|
'See adapters/README.md and skills/graphlin/SKILL.md for privacy and coverage.\n');
|
package/scripts/control.mjs
CHANGED
|
@@ -39,7 +39,7 @@ async function handle(line) {
|
|
|
39
39
|
const supported = ['2024-11-05', '2025-03-26', '2025-06-18'];
|
|
40
40
|
return result({ protocolVersion: supported.includes(message.params?.protocolVersion) ? message.params.protocolVersion : '2025-06-18',
|
|
41
41
|
capabilities: { tools: { listChanged: false } },
|
|
42
|
-
serverInfo: { name: 'graphlin', version: '0.
|
|
42
|
+
serverInfo: { name: 'graphlin', version: '0.2.0' },
|
|
43
43
|
instructions: 'Controls only. Passive host hooks provide observations when separately activated. No drawing calls after each action.' });
|
|
44
44
|
}
|
|
45
45
|
if (message.method === 'ping') return result({});
|
package/scripts/daemon.mjs
CHANGED
|
@@ -5,7 +5,8 @@ process.umask(0o077);
|
|
|
5
5
|
let server;
|
|
6
6
|
try {
|
|
7
7
|
const options = parseArguments(process.argv.slice(2), { worker: true });
|
|
8
|
-
const policy = {
|
|
8
|
+
const policy = { readSource: options.localSource || options.allowSource,
|
|
9
|
+
transmitSource: options.allowSource, persistEvidence: options.persistEvidence,
|
|
9
10
|
displayEvidence: options.displayEvidence };
|
|
10
11
|
let decisionService;
|
|
11
12
|
if (options.mode === 'demo') {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { projectPaths, defaultDataDir } from '../runtime/daemon/paths.mjs';
|
|
3
|
+
import { createExtensionRegistry, extensionError } from '../runtime/extensions/index.mjs';
|
|
4
|
+
|
|
5
|
+
/** Parent CLI dispatches its already-parsed extension arguments here. This
|
|
6
|
+
* module neither parses global CLI options nor starts/stops the daemon. */
|
|
7
|
+
export async function runExtensions(args, {
|
|
8
|
+
projectRoot, dataDir = defaultDataDir(), signal, transport, output = process.stdout,
|
|
9
|
+
registry: suppliedRegistry,
|
|
10
|
+
} = {}) {
|
|
11
|
+
if (!Array.isArray(args) || args.some(value => typeof value !== 'string')) throw extensionError('invalid_extension_arguments');
|
|
12
|
+
const [command = 'list', source, ...rest] = args;
|
|
13
|
+
if (!['list', 'add', 'update', 'remove', 'doctor', 'dev'].includes(command) || rest.length ||
|
|
14
|
+
(['add', 'update', 'remove', 'dev'].includes(command) ? !source : source !== undefined)) {
|
|
15
|
+
throw extensionError('usage_extensions_list_add_update_remove_doctor_dev');
|
|
16
|
+
}
|
|
17
|
+
let registry = suppliedRegistry;
|
|
18
|
+
if (!registry) {
|
|
19
|
+
const paths = await projectPaths(projectRoot ?? process.cwd(), dataDir);
|
|
20
|
+
registry = await createExtensionRegistry({ dataDir: paths.dataDir, projectId: paths.projectId, transport });
|
|
21
|
+
}
|
|
22
|
+
const resolveSource = value => value.startsWith('.') || path.isAbsolute(value)
|
|
23
|
+
? path.resolve(projectRoot ?? process.cwd(), value) : value;
|
|
24
|
+
let result;
|
|
25
|
+
if (command === 'list') result = await registry.list();
|
|
26
|
+
if (command === 'doctor') result = await registry.doctor();
|
|
27
|
+
if (command === 'remove') result = await registry.remove(source);
|
|
28
|
+
if (command === 'add' || command === 'update') result = await registry.install(resolveSource(source), { signal });
|
|
29
|
+
if (command === 'dev') {
|
|
30
|
+
if (!(source.startsWith('.') || path.isAbsolute(source))) throw extensionError('development_directory_required');
|
|
31
|
+
result = await registry.dev(resolveSource(source), { signal });
|
|
32
|
+
}
|
|
33
|
+
if (output) {
|
|
34
|
+
if (Array.isArray(result)) output.write(result.length ? result.map(row =>
|
|
35
|
+
`${row.id} ${row.version} ${row.digest.slice(0, 12)}${row.development ? ' development' : ''} ${row.grant ? 'granted' : 'approval required'}`
|
|
36
|
+
).join('\n') + '\n' : 'No visualizer extensions installed.\n');
|
|
37
|
+
else if (command === 'doctor') output.write(`${result.ok ? 'Extension checks passed.' : 'Extension checks failed.'}\n${
|
|
38
|
+
result.results.map(row => `${row.id ?? 'catalogue'}: ${row.code}`).join('\n')}${result.results.length ? '\n' : ''}`);
|
|
39
|
+
else output.write(command === 'remove' ? `Removed ${result.id} and its grants.\n` :
|
|
40
|
+
`Installed ${result.id} ${result.version}${result.development ? ' (development snapshot)' : ''}. ${
|
|
41
|
+
result.grant ? 'Existing digest approval retained.' : 'Project approval is required before data delivery.'}\n`);
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|