@hongmaple0820/scale-engine 0.49.0 → 0.50.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 (190) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/api/DashboardHttpConfig.d.ts +28 -0
  4. package/dist/api/DashboardHttpConfig.js +110 -0
  5. package/dist/api/DashboardHttpConfig.js.map +1 -0
  6. package/dist/api/cli.js +102 -11
  7. package/dist/api/cli.js.map +1 -1
  8. package/dist/api/http.d.ts +1 -0
  9. package/dist/api/http.js +50 -0
  10. package/dist/api/http.js.map +1 -0
  11. package/dist/artifact/types.d.ts +5 -0
  12. package/dist/artifact/types.js.map +1 -1
  13. package/dist/bootstrap/DependencyBootstrap.d.ts +1 -0
  14. package/dist/bootstrap/DependencyBootstrap.js +14 -3
  15. package/dist/bootstrap/DependencyBootstrap.js.map +1 -1
  16. package/dist/cli/cortexApplyCommand.d.ts +26 -0
  17. package/dist/cli/cortexApplyCommand.js +74 -0
  18. package/dist/cli/cortexApplyCommand.js.map +1 -0
  19. package/dist/cli/cortexCandidateCommands.d.ts +42 -0
  20. package/dist/cli/cortexCandidateCommands.js +119 -0
  21. package/dist/cli/cortexCandidateCommands.js.map +1 -0
  22. package/dist/cli/cortexCommands.d.ts +15 -0
  23. package/dist/cli/cortexCommands.js +57 -15
  24. package/dist/cli/cortexCommands.js.map +1 -1
  25. package/dist/cli/engineBootstrap.d.ts +1 -1
  26. package/dist/cli/engineBootstrap.js +2 -0
  27. package/dist/cli/engineBootstrap.js.map +1 -1
  28. package/dist/cli/evalCommands.js +1 -0
  29. package/dist/cli/evalCommands.js.map +1 -1
  30. package/dist/cli/phaseCommands.d.ts +28 -0
  31. package/dist/cli/phaseCommands.js +148 -9
  32. package/dist/cli/phaseCommands.js.map +1 -1
  33. package/dist/cli/runtimeSkillCommands.js +12 -2
  34. package/dist/cli/runtimeSkillCommands.js.map +1 -1
  35. package/dist/cli/shieldCommands.d.ts +1 -0
  36. package/dist/cli/shieldCommands.js +20 -7
  37. package/dist/cli/shieldCommands.js.map +1 -1
  38. package/dist/cli/workflowEvidenceCommands.d.ts +120 -0
  39. package/dist/cli/workflowEvidenceCommands.js +228 -2
  40. package/dist/cli/workflowEvidenceCommands.js.map +1 -1
  41. package/dist/cortex/AutoFixEventObservations.d.ts +11 -0
  42. package/dist/cortex/AutoFixEventObservations.js +72 -0
  43. package/dist/cortex/AutoFixEventObservations.js.map +1 -0
  44. package/dist/cortex/GateEvidenceObservations.d.ts +22 -0
  45. package/dist/cortex/GateEvidenceObservations.js +179 -0
  46. package/dist/cortex/GateEvidenceObservations.js.map +1 -0
  47. package/dist/cortex/GovernanceMetrics.d.ts +2 -0
  48. package/dist/cortex/GovernanceMetrics.js +112 -22
  49. package/dist/cortex/GovernanceMetrics.js.map +1 -1
  50. package/dist/cortex/InstinctApplicationRecorder.d.ts +28 -0
  51. package/dist/cortex/InstinctApplicationRecorder.js +145 -0
  52. package/dist/cortex/InstinctApplicationRecorder.js.map +1 -0
  53. package/dist/cortex/InstinctCandidateAudit.d.ts +3 -0
  54. package/dist/cortex/InstinctCandidateAudit.js +39 -0
  55. package/dist/cortex/InstinctCandidateAudit.js.map +1 -0
  56. package/dist/cortex/InstinctCandidateReview.d.ts +32 -0
  57. package/dist/cortex/InstinctCandidateReview.js +125 -0
  58. package/dist/cortex/InstinctCandidateReview.js.map +1 -0
  59. package/dist/cortex/InstinctExtractor.d.ts +1 -0
  60. package/dist/cortex/InstinctExtractor.js +24 -17
  61. package/dist/cortex/InstinctExtractor.js.map +1 -1
  62. package/dist/cortex/InstinctRuntimeEvidence.d.ts +14 -0
  63. package/dist/cortex/InstinctRuntimeEvidence.js +120 -0
  64. package/dist/cortex/InstinctRuntimeEvidence.js.map +1 -0
  65. package/dist/cortex/InstinctStore.d.ts +18 -3
  66. package/dist/cortex/InstinctStore.js +30 -9
  67. package/dist/cortex/InstinctStore.js.map +1 -1
  68. package/dist/cortex/SessionInjector.d.ts +1 -0
  69. package/dist/cortex/SessionInjector.js +15 -2
  70. package/dist/cortex/SessionInjector.js.map +1 -1
  71. package/dist/dashboard/DashboardServer.d.ts +79 -0
  72. package/dist/dashboard/DashboardServer.js +330 -6
  73. package/dist/dashboard/DashboardServer.js.map +1 -1
  74. package/dist/dashboard/spa/app.js +515 -0
  75. package/dist/dashboard/spa/components/DataTable.js +53 -0
  76. package/dist/dashboard/spa/components/EventStream.js +66 -0
  77. package/dist/dashboard/spa/components/LoadingState.js +39 -0
  78. package/dist/dashboard/spa/components/MetricCard.js +30 -0
  79. package/dist/dashboard/spa/components/Panel.js +27 -0
  80. package/dist/dashboard/spa/components/StatusBadge.js +51 -0
  81. package/dist/dashboard/spa/i18n.js +767 -0
  82. package/dist/dashboard/spa/index.html +463 -0
  83. package/dist/dashboard/spa/pages/costs.js +522 -0
  84. package/dist/dashboard/spa/pages/documents.js +540 -0
  85. package/dist/dashboard/spa/pages/knowledge.js +457 -0
  86. package/dist/dashboard/spa/pages/monitoring.js +361 -0
  87. package/dist/dashboard/spa/pages/overview.js +301 -0
  88. package/dist/dashboard/spa/pages/topology-renderers.js +251 -0
  89. package/dist/dashboard/spa/pages/topology.js +370 -0
  90. package/dist/dashboard/spa/pages/workflow-renderers.js +239 -0
  91. package/dist/dashboard/spa/pages/workflow.js +217 -0
  92. package/dist/env/EnvironmentDoctor.js +12 -7
  93. package/dist/env/EnvironmentDoctor.js.map +1 -1
  94. package/dist/eval/WorkflowEval.d.ts +9 -0
  95. package/dist/eval/WorkflowEval.js +348 -2
  96. package/dist/eval/WorkflowEval.js.map +1 -1
  97. package/dist/memory/MemoryBrain.d.ts +13 -0
  98. package/dist/memory/MemoryBrain.js +47 -0
  99. package/dist/memory/MemoryBrain.js.map +1 -1
  100. package/dist/memory/MemoryFabric.d.ts +1 -0
  101. package/dist/memory/MemoryFabric.js +12 -8
  102. package/dist/memory/MemoryFabric.js.map +1 -1
  103. package/dist/memory/MemoryLearning.d.ts +1 -0
  104. package/dist/memory/MemoryLearning.js +6 -3
  105. package/dist/memory/MemoryLearning.js.map +1 -1
  106. package/dist/memory/MemoryProviders.d.ts +8 -1
  107. package/dist/memory/MemoryProviders.js +143 -29
  108. package/dist/memory/MemoryProviders.js.map +1 -1
  109. package/dist/runtime/AiOsRuntime.d.ts +14 -1
  110. package/dist/runtime/AiOsRuntime.js +59 -3
  111. package/dist/runtime/AiOsRuntime.js.map +1 -1
  112. package/dist/runtime/RuntimeDoctor.js +3 -1
  113. package/dist/runtime/RuntimeDoctor.js.map +1 -1
  114. package/dist/runtime/RuntimeEvidenceLedger.d.ts +6 -0
  115. package/dist/runtime/RuntimeEvidenceLedger.js +52 -1
  116. package/dist/runtime/RuntimeEvidenceLedger.js.map +1 -1
  117. package/dist/runtime/SessionLedger.d.ts +2 -0
  118. package/dist/runtime/SessionLedger.js +4 -0
  119. package/dist/runtime/SessionLedger.js.map +1 -1
  120. package/dist/setup/SetupVerification.js +53 -5
  121. package/dist/setup/SetupVerification.js.map +1 -1
  122. package/dist/shield/PolicyCompiler.js +73 -12
  123. package/dist/shield/PolicyCompiler.js.map +1 -1
  124. package/dist/shield/ProtectedPaths.js +4 -2
  125. package/dist/shield/ProtectedPaths.js.map +1 -1
  126. package/dist/skills/SkillCatalog.d.ts +2 -0
  127. package/dist/skills/SkillCatalog.js +8 -0
  128. package/dist/skills/SkillCatalog.js.map +1 -1
  129. package/dist/skills/SkillDoctor.d.ts +19 -2
  130. package/dist/skills/SkillDoctor.js +163 -13
  131. package/dist/skills/SkillDoctor.js.map +1 -1
  132. package/dist/tools/SafeCommandRunner.d.ts +1 -0
  133. package/dist/tools/SafeCommandRunner.js +1 -0
  134. package/dist/tools/SafeCommandRunner.js.map +1 -1
  135. package/dist/tools/ToolCapabilityRegistry.js +25 -3
  136. package/dist/tools/ToolCapabilityRegistry.js.map +1 -1
  137. package/dist/tools/ToolOrchestrator.js +21 -0
  138. package/dist/tools/ToolOrchestrator.js.map +1 -1
  139. package/dist/version.d.ts +1 -1
  140. package/dist/version.js +1 -1
  141. package/dist/workflow/AgentLoopReadiness.d.ts +103 -0
  142. package/dist/workflow/AgentLoopReadiness.js +371 -0
  143. package/dist/workflow/AgentLoopReadiness.js.map +1 -0
  144. package/dist/workflow/EcosystemReadinessGate.d.ts +46 -0
  145. package/dist/workflow/EcosystemReadinessGate.js +126 -0
  146. package/dist/workflow/EcosystemReadinessGate.js.map +1 -0
  147. package/dist/workflow/EngineeringStandards.js +48 -3
  148. package/dist/workflow/EngineeringStandards.js.map +1 -1
  149. package/dist/workflow/GateCatalog.js +9 -0
  150. package/dist/workflow/GateCatalog.js.map +1 -1
  151. package/dist/workflow/GovernanceTemplatePacks.js +2 -26
  152. package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
  153. package/dist/workflow/GovernanceTemplates.js +8 -1
  154. package/dist/workflow/GovernanceTemplates.js.map +1 -1
  155. package/dist/workflow/ReleaseDeploymentLedger.d.ts +63 -0
  156. package/dist/workflow/ReleaseDeploymentLedger.js +154 -0
  157. package/dist/workflow/ReleaseDeploymentLedger.js.map +1 -0
  158. package/dist/workflow/ReviewAnalyzer.js +50 -3
  159. package/dist/workflow/ReviewAnalyzer.js.map +1 -1
  160. package/dist/workflow/SessionPreamble.d.ts +7 -0
  161. package/dist/workflow/SessionPreamble.js +48 -9
  162. package/dist/workflow/SessionPreamble.js.map +1 -1
  163. package/dist/workflow/VerificationCommands.d.ts +1 -0
  164. package/dist/workflow/VerificationCommands.js.map +1 -1
  165. package/dist/workflow/VerificationProfile.d.ts +5 -0
  166. package/dist/workflow/VerificationProfile.js +26 -0
  167. package/dist/workflow/VerificationProfile.js.map +1 -1
  168. package/dist/workflow/VerificationSchema.d.ts +3 -0
  169. package/dist/workflow/VerificationSchema.js +6 -0
  170. package/dist/workflow/VerificationSchema.js.map +1 -1
  171. package/dist/workflow/WorkflowEffectiveness.d.ts +97 -0
  172. package/dist/workflow/WorkflowEffectiveness.js +302 -0
  173. package/dist/workflow/WorkflowEffectiveness.js.map +1 -0
  174. package/dist/workflow/WorkflowEffectivenessRenderer.d.ts +2 -0
  175. package/dist/workflow/WorkflowEffectivenessRenderer.js +67 -0
  176. package/dist/workflow/WorkflowEffectivenessRenderer.js.map +1 -0
  177. package/dist/workflow/WorkflowEffectivenessScoring.d.ts +6 -0
  178. package/dist/workflow/WorkflowEffectivenessScoring.js +243 -0
  179. package/dist/workflow/WorkflowEffectivenessScoring.js.map +1 -0
  180. package/dist/workflow/gates/GateSystem.d.ts +16 -0
  181. package/dist/workflow/gates/GateSystem.js +208 -41
  182. package/dist/workflow/gates/GateSystem.js.map +1 -1
  183. package/dist/workflow/gates/MetaGovernanceGates.js +269 -8
  184. package/dist/workflow/gates/MetaGovernanceGates.js.map +1 -1
  185. package/docs/reference/cli.md +2 -1
  186. package/docs/start/agent-governance-demo.md +1 -1
  187. package/docs/workflow/README.md +1 -1
  188. package/docs/workflow/templates/github-actions-scale-preflight.yml +4 -1
  189. package/package.json +6 -3
  190. package/scripts/workflow/run-vitest.mjs +123 -0
@@ -0,0 +1,463 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SCALE Engine — Dashboard</title>
7
+ <style>
8
+ :root {
9
+ --bg-0: #0a0a0a; --bg-1: #111111; --bg-2: #191919; --bg-3: #222222;
10
+ --border: #2a2a2a; --border-hover: #3a3a3a;
11
+ --text-0: #ededed; --text-1: #a1a1a1; --text-2: #666666;
12
+ --accent: #00dc82; --accent-dim: rgba(0,220,130,0.15); --accent-hover: #00f090;
13
+ --danger: #ff4444; --warning: #ffaa00; --info: #5588ff;
14
+ --radius: 8px; --radius-lg: 12px;
15
+ --shadow: 0 1px 3px rgba(0,0,0,0.3);
16
+ --transition: 150ms ease;
17
+ --sidebar-w: 240px;
18
+ --header-h: 56px;
19
+ }
20
+ [data-theme="light"] {
21
+ --bg-0: #ffffff; --bg-1: #fafafa; --bg-2: #f5f5f5; --bg-3: #eeeeee;
22
+ --border: #e0e0e0; --border-hover: #cccccc;
23
+ --text-0: #111111; --text-1: #555555; --text-2: #999999;
24
+ --accent: #00b868; --accent-dim: rgba(0,184,104,0.1); --accent-hover: #00a058;
25
+ --shadow: 0 1px 3px rgba(0,0,0,0.08);
26
+ }
27
+ * { box-sizing: border-box; margin: 0; padding: 0; }
28
+ body {
29
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', sans-serif;
30
+ background: var(--bg-0); color: var(--text-0);
31
+ display: flex; min-height: 100vh;
32
+ -webkit-font-smoothing: antialiased;
33
+ }
34
+ a { color: var(--accent); text-decoration: none; }
35
+ a:hover { color: var(--accent-hover); }
36
+ button { font-family: inherit; cursor: pointer; }
37
+
38
+ /* ── Sidebar ──────────────────────────────────────────────────── */
39
+ .sidebar {
40
+ width: var(--sidebar-w); min-width: var(--sidebar-w);
41
+ background: var(--bg-1); border-right: 1px solid var(--border);
42
+ display: flex; flex-direction: column;
43
+ position: fixed; top: 0; left: 0; bottom: 0;
44
+ z-index: 100;
45
+ }
46
+ .sidebar-brand {
47
+ padding: 16px 20px; display: flex; align-items: center; gap: 10px;
48
+ border-bottom: 1px solid var(--border);
49
+ font-weight: 600; font-size: 15px;
50
+ }
51
+ .sidebar-brand .logo {
52
+ width: 28px; height: 28px; background: var(--accent);
53
+ border-radius: 6px; display: flex; align-items: center; justify-content: center;
54
+ color: #000; font-weight: 700; font-size: 14px;
55
+ }
56
+ .sidebar-nav { flex: 1; padding: 12px 8px; overflow-y: auto; }
57
+ .nav-section { padding: 8px 12px 4px; font-size: 11px; color: var(--text-2); text-transform: uppercase; letter-spacing: 0.5px; }
58
+ .nav-item {
59
+ display: flex; align-items: center; gap: 10px;
60
+ padding: 8px 12px; border-radius: var(--radius);
61
+ color: var(--text-1); font-size: 14px; transition: all var(--transition);
62
+ cursor: pointer; user-select: none;
63
+ }
64
+ .nav-item:hover { background: var(--bg-3); color: var(--text-0); }
65
+ .nav-item.active { background: var(--accent-dim); color: var(--accent); }
66
+ .nav-item .icon { width: 18px; text-align: center; font-size: 15px; }
67
+ .nav-item .badge {
68
+ margin-left: auto; background: var(--accent); color: #000;
69
+ padding: 1px 6px; border-radius: 10px; font-size: 11px; font-weight: 600;
70
+ }
71
+ .sidebar-footer {
72
+ padding: 12px 16px; border-top: 1px solid var(--border);
73
+ display: flex; align-items: center; justify-content: space-between;
74
+ }
75
+ .footer-controls { display: flex; align-items: center; gap: 6px; }
76
+ .theme-toggle, .lang-toggle {
77
+ background: var(--bg-3); border: 1px solid var(--border);
78
+ color: var(--text-1); padding: 6px 10px; border-radius: var(--radius);
79
+ font-size: 13px; transition: all var(--transition);
80
+ }
81
+ .theme-toggle:hover, .lang-toggle:hover { border-color: var(--border-hover); color: var(--text-0); }
82
+ .sse-status { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); }
83
+ .sse-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--danger); }
84
+ .sse-dot.connected { background: var(--accent); }
85
+
86
+ /* ── Main Content ─────────────────────────────────────────────── */
87
+ .main { flex: 1; margin-left: var(--sidebar-w); display: flex; flex-direction: column; min-height: 100vh; }
88
+ .header {
89
+ height: var(--header-h); padding: 0 24px;
90
+ display: flex; align-items: center; justify-content: space-between;
91
+ border-bottom: 1px solid var(--border); background: var(--bg-1);
92
+ position: sticky; top: 0; z-index: 50;
93
+ }
94
+ .header-title { font-size: 18px; font-weight: 600; }
95
+ .header-actions { display: flex; align-items: center; gap: 12px; }
96
+ .search-box {
97
+ background: var(--bg-2); border: 1px solid var(--border);
98
+ color: var(--text-0); padding: 7px 12px; border-radius: var(--radius);
99
+ font-size: 13px; width: 220px; transition: all var(--transition);
100
+ }
101
+ .search-box:focus { outline: none; border-color: var(--accent); }
102
+ .search-box::placeholder { color: var(--text-2); }
103
+ .content { flex: 1; padding: 24px; overflow-y: auto; }
104
+ .page-toolbar {
105
+ display: flex; gap: 12px; margin-bottom: 16px; align-items: center; flex-wrap: wrap;
106
+ }
107
+ .toolbar-spacer { flex: 1; min-width: 12px; }
108
+ .data-note {
109
+ display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center;
110
+ padding: 10px 12px; margin-bottom: 16px; border: 1px solid var(--border);
111
+ border-radius: var(--radius); background: var(--bg-1); color: var(--text-1);
112
+ font-size: 12px; line-height: 1.5;
113
+ }
114
+ .data-note strong { color: var(--text-0); font-weight: 600; }
115
+ .action-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
116
+ .field-label { display: inline-flex; gap: 8px; align-items: center; color: var(--text-1); font-size: 12px; }
117
+ .field-label input[type="checkbox"] { accent-color: var(--accent); }
118
+ .section-copy { color: var(--text-2); font-size: 12px; line-height: 1.6; }
119
+ .auto-refresh-control {
120
+ padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius);
121
+ background: var(--bg-1);
122
+ }
123
+
124
+ /* ── Cards & Widgets ──────────────────────────────────────────── */
125
+ .metrics-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; }
126
+ .metric-card {
127
+ background: var(--bg-1); border: 1px solid var(--border);
128
+ border-radius: var(--radius-lg); padding: 20px;
129
+ transition: border-color var(--transition);
130
+ }
131
+ .metric-card:hover { border-color: var(--border-hover); }
132
+ .metric-label { font-size: 13px; color: var(--text-1); margin-bottom: 8px; }
133
+ .metric-value { font-size: 28px; font-weight: 700; color: var(--text-0); }
134
+ .metric-value.accent { color: var(--accent); }
135
+ .metric-change { font-size: 12px; margin-top: 4px; }
136
+ .metric-change.up { color: var(--accent); }
137
+ .metric-change.down { color: var(--danger); }
138
+
139
+ .chart-container {
140
+ background: var(--bg-1); border: 1px solid var(--border);
141
+ border-radius: var(--radius-lg); padding: 20px; margin-bottom: 24px;
142
+ }
143
+ .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
144
+ .chart-title { font-size: 15px; font-weight: 600; }
145
+ .chart-area { width: 100%; height: 300px; }
146
+
147
+ .panel {
148
+ background: var(--bg-1); border: 1px solid var(--border);
149
+ border-radius: var(--radius-lg); padding: 20px; margin-bottom: 24px;
150
+ }
151
+ .panel-title { font-size: 15px; font-weight: 600; margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
152
+ .panel-title .count { color: var(--text-2); font-weight: 400; font-size: 13px; }
153
+
154
+ /* ── Status Badges ────────────────────────────────────────────── */
155
+ .badge-status {
156
+ display: inline-block; padding: 2px 8px; border-radius: 4px;
157
+ font-size: 12px; font-weight: 500;
158
+ }
159
+ .badge-DRAFT { background: #333; color: #999; }
160
+ .badge-REVIEWING { background: rgba(255,170,0,0.15); color: #ffaa00; }
161
+ .badge-FROZEN { background: rgba(85,136,255,0.15); color: #5588ff; }
162
+ .badge-COMPLETED { background: rgba(0,220,130,0.15); color: #00dc82; }
163
+ .badge-BLOCKED { background: rgba(255,68,68,0.15); color: #ff4444; }
164
+ .badge-IN_PROGRESS { background: rgba(255,170,0,0.15); color: #ffaa00; }
165
+ .badge-DONE { background: rgba(0,220,130,0.15); color: #00dc82; }
166
+ .badge-PROPOSED { background: rgba(85,136,255,0.15); color: #5588ff; }
167
+ .badge-APPROVED { background: rgba(0,220,130,0.15); color: #00dc82; }
168
+ .badge-REJECTED { background: rgba(255,68,68,0.15); color: #ff4444; }
169
+
170
+ .severity-badge { display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 11px; font-weight: 500; }
171
+ .severity-low { background: rgba(0,220,130,0.15); color: #00dc82; }
172
+ .severity-medium { background: rgba(255,170,0,0.15); color: #ffaa00; }
173
+ .severity-high { background: rgba(255,68,68,0.15); color: #ff4444; }
174
+ .severity-critical { background: rgba(255,0,0,0.2); color: #ff2222; }
175
+
176
+ /* ── Tables ───────────────────────────────────────────────────── */
177
+ .data-table { width: 100%; border-collapse: collapse; }
178
+ .data-table th { text-align: left; padding: 8px 12px; font-size: 12px; color: var(--text-2); font-weight: 500; border-bottom: 1px solid var(--border); }
179
+ .data-table td { padding: 10px 12px; font-size: 13px; border-bottom: 1px solid var(--bg-3); }
180
+ .data-table tr:hover td { background: var(--bg-2); }
181
+
182
+ /* ── Event Stream ─────────────────────────────────────────────── */
183
+ .event-stream { max-height: 400px; overflow-y: auto; }
184
+ .event-item {
185
+ display: flex; align-items: center; gap: 12px;
186
+ padding: 8px 0; border-bottom: 1px solid var(--bg-3);
187
+ font-size: 13px;
188
+ }
189
+ .event-type {
190
+ background: var(--accent-dim); color: var(--accent);
191
+ padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 500;
192
+ white-space: nowrap;
193
+ }
194
+ .event-time { color: var(--text-2); font-size: 12px; white-space: nowrap; }
195
+
196
+ /* ── Artifact Cards ───────────────────────────────────────────── */
197
+ .artifact-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
198
+ .artifact-card {
199
+ background: var(--bg-1); border: 1px solid var(--border);
200
+ border-radius: var(--radius-lg); padding: 16px;
201
+ transition: border-color var(--transition);
202
+ }
203
+ .artifact-card:hover { border-color: var(--border-hover); }
204
+ .artifact-card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
205
+ .artifact-card-title { font-size: 14px; font-weight: 600; }
206
+ .artifact-card-meta { font-size: 12px; color: var(--text-2); margin-bottom: 12px; }
207
+ .artifact-gates { display: flex; flex-wrap: wrap; gap: 6px; }
208
+ .gate-pill {
209
+ padding: 2px 8px; border-radius: 4px; font-size: 11px;
210
+ background: var(--bg-3); color: var(--text-1);
211
+ }
212
+ .gate-pill.passed { background: rgba(0,220,130,0.15); color: #00dc82; }
213
+ .gate-pill.failed { background: rgba(255,68,68,0.15); color: #ff4444; }
214
+
215
+ /* ── Document Viewer ──────────────────────────────────────────── */
216
+ .doc-layout {
217
+ display: grid; grid-template-columns: 260px 1fr; gap: 24px;
218
+ min-height: calc(100vh - var(--header-h) - 96px); align-items: start;
219
+ }
220
+ .doc-tree {
221
+ background: var(--bg-1); border: 1px solid var(--border);
222
+ border-radius: var(--radius-lg); padding: 16px; overflow-y: auto;
223
+ position: sticky; top: 0; max-height: calc(100vh - var(--header-h) - 96px);
224
+ }
225
+ .doc-tree-item {
226
+ padding: 6px 8px; border-radius: var(--radius); font-size: 13px;
227
+ cursor: pointer; color: var(--text-1); transition: all var(--transition);
228
+ }
229
+ .doc-tree-item:hover { background: var(--bg-3); color: var(--text-0); }
230
+ .doc-tree-item.active { background: var(--accent-dim); color: var(--accent); }
231
+ .doc-tree-folder { font-weight: 600; color: var(--text-0); padding: 8px 8px 4px; font-size: 12px; text-transform: uppercase; }
232
+ .doc-renderer {
233
+ background: var(--bg-1); border: 1px solid var(--border);
234
+ border-radius: var(--radius-lg); padding: 24px; overflow-y: auto;
235
+ min-height: calc(100vh - var(--header-h) - 96px);
236
+ }
237
+ .doc-renderer iframe { width: 100%; height: 100%; border: none; min-height: 600px; }
238
+ .prototype-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }
239
+ .prototype-card {
240
+ border: 1px solid var(--border); border-radius: var(--radius-lg);
241
+ background: var(--bg-2); overflow: hidden;
242
+ }
243
+ .prototype-preview {
244
+ height: 150px; border-bottom: 1px solid var(--border); background: var(--bg-0); overflow: hidden;
245
+ }
246
+ .prototype-preview iframe {
247
+ width: 100%; height: 300px; transform: scale(0.5); transform-origin: top left;
248
+ border: 0; pointer-events: none; background: white;
249
+ }
250
+ .prototype-body { padding: 12px; display: flex; flex-direction: column; gap: 10px; }
251
+ .prototype-title { font-size: 13px; font-weight: 600; color: var(--text-0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
252
+ .prototype-meta { color: var(--text-2); font-size: 12px; }
253
+ .review-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 12px; }
254
+ .review-item { border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; background: var(--bg-2); }
255
+ .review-count { font-size: 22px; font-weight: 700; color: var(--text-0); }
256
+ .review-label { font-size: 12px; color: var(--text-2); margin-top: 4px; }
257
+
258
+ /* ── Utilities ────────────────────────────────────────────────── */
259
+ .flex { display: flex; }
260
+ .flex-col { flex-direction: column; }
261
+ .gap-16 { gap: 16px; }
262
+ .gap-24 { gap: 24px; }
263
+ .mb-24 { margin-bottom: 24px; }
264
+ .text-muted { color: var(--text-2); }
265
+ .text-sm { font-size: 13px; }
266
+ .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
267
+ .grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 24px; }
268
+ .loading-placeholder {
269
+ background: var(--bg-2); border-radius: var(--radius);
270
+ height: 200px; display: flex; align-items: center; justify-content: center;
271
+ color: var(--text-2); font-size: 14px;
272
+ }
273
+ .empty-state {
274
+ text-align: center; padding: 48px 24px; color: var(--text-2);
275
+ }
276
+ .empty-state .icon { font-size: 32px; margin-bottom: 12px; }
277
+ .tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
278
+ .tab {
279
+ padding: 8px 16px; font-size: 13px; color: var(--text-1);
280
+ cursor: pointer; border-bottom: 2px solid transparent;
281
+ transition: all var(--transition);
282
+ }
283
+ .tab:hover { color: var(--text-0); }
284
+ .tab.active { color: var(--accent); border-bottom-color: var(--accent); }
285
+
286
+ /* ── Markdown Body ────────────────────────────────────────────── */
287
+ .markdown-body h1, .markdown-body h2, .markdown-body h3 { color: var(--text-0); }
288
+ .markdown-body a { color: var(--accent); }
289
+ .markdown-body code { background: var(--bg-2); padding: 2px 5px; border-radius: 3px; font-size: 12px; }
290
+ .markdown-body pre { background: var(--bg-2); padding: 12px; border-radius: var(--radius); overflow-x: auto; }
291
+ .markdown-body blockquote { border-left: 3px solid var(--accent); padding-left: 12px; color: var(--text-1); margin: 12px 0; }
292
+ .markdown-body table { border-collapse: collapse; width: 100%; margin: 12px 0; }
293
+ .markdown-body th, .markdown-body td { border: 1px solid var(--border); padding: 6px 10px; text-align: left; }
294
+ .markdown-body th { background: var(--bg-2); font-weight: 600; }
295
+ .markdown-body img { max-width: 100%; border-radius: var(--radius); }
296
+
297
+ /* ── Doc Favorites ────────────────────────────────────────────── */
298
+ .doc-fav-btn:hover { color: #ffaa00 !important; transform: scale(1.2); }
299
+ .doc-fav-btn { transition: all var(--transition); display: inline-flex; }
300
+
301
+ /* ── Topology Legend Items ─────────────────────────────────────── */
302
+ .topo-legend-item:hover, .topo-kind-item:hover, .topo-domain-item:hover {
303
+ background: var(--bg-3);
304
+ }
305
+
306
+ /* ── Scrollbar ────────────────────────────────────────────────── */
307
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
308
+ ::-webkit-scrollbar-track { background: transparent; }
309
+ ::-webkit-scrollbar-thumb { background: var(--bg-3); border-radius: 3px; }
310
+ ::-webkit-scrollbar-thumb:hover { background: var(--border-hover); }
311
+
312
+ /* ── Topology ─────────────────────────────────────────────────── */
313
+ #topology-cy { width: 100%; height: calc(100vh - var(--header-h) - 48px); background: var(--bg-0); border-radius: var(--radius-lg); }
314
+ .topology-controls { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
315
+ .topo-btn {
316
+ padding: 6px 12px; border-radius: var(--radius);
317
+ background: var(--bg-2); border: 1px solid var(--border);
318
+ color: var(--text-1); font-size: 12px; transition: all var(--transition);
319
+ cursor: pointer;
320
+ }
321
+ .topo-btn:hover, .topo-btn.active { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }
322
+ .topo-btn:focus-visible, .tab:focus-visible, .nav-item:focus-visible, .doc-tree-item:focus-visible {
323
+ outline: 2px solid var(--accent); outline-offset: 2px;
324
+ }
325
+
326
+ /* ── Components ──────────────────────────────────────────────── */
327
+ .badge {
328
+ display: inline-block; padding: 2px 8px; border-radius: 10px;
329
+ font-size: 11px; font-weight: 500; line-height: 1.4;
330
+ }
331
+ .badge-accent { background: var(--accent-dim); color: var(--accent); }
332
+ .badge-success { background: rgba(0,220,130,0.15); color: #00dc82; }
333
+ .badge-warning { background: rgba(255,170,0,0.15); color: #ffaa00; }
334
+ .badge-danger { background: rgba(255,68,68,0.15); color: #ff4444; }
335
+ .badge-info { background: rgba(85,136,255,0.15); color: #5588ff; }
336
+ .badge-muted { background: var(--bg-3); color: var(--text-2); }
337
+
338
+ .data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
339
+ .data-table th {
340
+ text-align: left; padding: 8px 12px; font-weight: 500; font-size: 11px;
341
+ color: var(--text-2); text-transform: uppercase; letter-spacing: 0.5px;
342
+ border-bottom: 1px solid var(--border);
343
+ }
344
+ .data-table td { padding: 8px 12px; border-bottom: 1px solid var(--border); }
345
+ .data-table tr:hover td { background: var(--bg-2); }
346
+ .table-wrap { overflow-x: auto; }
347
+
348
+ .loading-state, .empty-state {
349
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
350
+ padding: 48px 24px; gap: 12px;
351
+ }
352
+ .loading-spinner {
353
+ width: 24px; height: 24px; border: 2px solid var(--border);
354
+ border-top-color: var(--accent); border-radius: 50%;
355
+ animation: spin 0.6s linear infinite;
356
+ }
357
+ @keyframes spin { to { transform: rotate(360deg); } }
358
+ .empty-icon { font-size: 32px; opacity: 0.5; }
359
+ .empty-title { font-size: 14px; font-weight: 500; }
360
+ .empty-desc { font-size: 12px; }
361
+
362
+ .metric-icon { font-size: 20px; margin-bottom: 4px; }
363
+
364
+ .event-icon { font-size: 14px; width: 20px; text-align: center; }
365
+ .event-icon.accent { color: var(--accent); }
366
+ .event-icon.danger { color: var(--danger); }
367
+ .event-icon.warning { color: var(--warning); }
368
+ .event-icon.info { color: var(--info); }
369
+ .event-icon.success { color: var(--accent); }
370
+ .event-type { font-size: 12px; font-weight: 500; }
371
+ .event-time { font-size: 11px; color: var(--text-2); margin-left: auto; }
372
+
373
+ /* ── Responsive ───────────────────────────────────────────────── */
374
+ @media (max-width: 768px) {
375
+ .sidebar { transform: translateX(-100%); }
376
+ .main { margin-left: 0; }
377
+ .grid-2, .grid-3 { grid-template-columns: 1fr; }
378
+ .doc-layout { grid-template-columns: 1fr; }
379
+ .doc-tree { position: static; max-height: 320px; }
380
+ .page-toolbar { align-items: stretch; }
381
+ .page-toolbar .search-box { width: 100%; max-width: none !important; }
382
+ .toolbar-spacer { display: none; }
383
+ }
384
+ </style>
385
+ </head>
386
+ <body>
387
+ <!-- Sidebar -->
388
+ <nav class="sidebar">
389
+ <div class="sidebar-brand">
390
+ <div class="logo">S</div>
391
+ <span>SCALE Engine</span>
392
+ </div>
393
+ <div class="sidebar-nav">
394
+ <div class="nav-section" data-i18n="nav.dashboard">Dashboard</div>
395
+ <div class="nav-item active" data-page="overview">
396
+ <span class="icon">&#9632;</span> <span data-i18n="nav.overview">Overview</span>
397
+ </div>
398
+ <div class="nav-item" data-page="workflow">
399
+ <span class="icon">&#9654;</span> <span data-i18n="nav.workflow">Workflow</span>
400
+ </div>
401
+ <div class="nav-item" data-page="topology">
402
+ <span class="icon">&#9670;</span> <span data-i18n="nav.topology">Topology</span>
403
+ </div>
404
+ <div class="nav-section" data-i18n="nav.operations">Operations</div>
405
+ <div class="nav-item" data-page="monitoring">
406
+ <span class="icon">&#9673;</span> <span data-i18n="nav.monitoring">Monitoring</span>
407
+ </div>
408
+ <div class="nav-item" data-page="costs">
409
+ <span class="icon">&#9660;</span> <span data-i18n="nav.costs">Costs</span>
410
+ </div>
411
+ <div class="nav-section" data-i18n="nav.content">Content</div>
412
+ <div class="nav-item" data-page="documents">
413
+ <span class="icon">&#9776;</span> <span data-i18n="nav.documents">Documents</span>
414
+ </div>
415
+ <div class="nav-item" data-page="knowledge">
416
+ <span class="icon">&#9678;</span> <span data-i18n="nav.knowledge">Knowledge</span>
417
+ </div>
418
+ </div>
419
+ <div class="sidebar-footer">
420
+ <div class="sse-status">
421
+ <div class="sse-dot" id="sse-dot"></div>
422
+ <span id="sse-label" data-i18n="sse.disconnected">Disconnected</span>
423
+ </div>
424
+ <div class="footer-controls">
425
+ <button class="lang-toggle" id="lang-toggle" title="Switch language">EN</button>
426
+ <button class="theme-toggle" id="theme-toggle" title="Toggle theme">&#9790;</button>
427
+ </div>
428
+ </div>
429
+ </nav>
430
+
431
+ <!-- Main Content -->
432
+ <div class="main">
433
+ <header class="header">
434
+ <h1 class="header-title" id="page-title">Overview</h1>
435
+ <div class="header-actions">
436
+ <input type="text" class="search-box" placeholder="Search..." id="global-search" data-i18n-placeholder="header.search">
437
+ </div>
438
+ </header>
439
+ <div class="content" id="app"></div>
440
+ </div>
441
+
442
+ <!-- Scripts -->
443
+ <script src="https://cdn.jsdelivr.net/npm/echarts@5.6.0/dist/echarts.min.js"></script>
444
+ <script src="/spa/i18n.js"></script>
445
+ <script src="/spa/app.js"></script>
446
+ <script src="/spa/components/MetricCard.js"></script>
447
+ <script src="/spa/components/Panel.js"></script>
448
+ <script src="/spa/components/StatusBadge.js"></script>
449
+ <script src="/spa/components/DataTable.js"></script>
450
+ <script src="/spa/components/EventStream.js"></script>
451
+ <script src="/spa/components/LoadingState.js"></script>
452
+ <script src="/spa/pages/overview.js"></script>
453
+ <script src="/spa/pages/workflow-renderers.js"></script>
454
+ <script src="/spa/pages/workflow.js"></script>
455
+ <script src="/spa/pages/monitoring.js"></script>
456
+ <script src="/spa/pages/costs.js"></script>
457
+ <script src="/spa/pages/documents.js"></script>
458
+ <script src="/spa/pages/knowledge.js"></script>
459
+ <script src="/spa/pages/topology-renderers.js"></script>
460
+ <script src="/spa/pages/topology.js"></script>
461
+ <script>window.Dashboard?.navigate(location.hash.slice(1) || 'overview')</script>
462
+ </body>
463
+ </html>