total-recall-brain 3.32.3 → 3.33.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/README.md +3 -1
- package/bin/total-recall.mjs +3 -0
- package/docs/ARCHITECTURE.md +21 -4
- package/docs/SSSS.md +230 -0
- package/docs/reference/CLI_INVENTORY.md +77 -0
- package/docs/reference/cli-reference.md +610 -0
- package/frontend/dist/assets/{index-DGMNZi_1.js → index-BPrkIYkZ.js} +174 -130
- package/frontend/dist/index.html +1 -1
- package/frontend/src/App.tsx +8 -4
- package/frontend/src/api/plugins.ts +80 -0
- package/frontend/src/components/brand/AnimatedBrandMark.tsx +163 -0
- package/frontend/src/components/brand/BrandMark.spec.tsx +4 -4
- package/frontend/src/components/brand/BrandMark.tsx +12 -3
- package/frontend/src/components/plugins/previews/CodeQualityPreview.tsx +130 -0
- package/frontend/src/components/plugins/previews/ComposableCliPreview.tsx +131 -0
- package/frontend/src/components/plugins/previews/DecisionPreview.tsx +156 -0
- package/frontend/src/components/plugins/previews/DesignPreview.tsx +118 -0
- package/frontend/src/components/plugins/previews/DomainsPreview.tsx +139 -0
- package/frontend/src/components/plugins/previews/PhonePreview.tsx +86 -0
- package/frontend/src/components/plugins/previews/SigningPreview.tsx +109 -0
- package/frontend/src/components/plugins/previews/TextPreview.tsx +144 -0
- package/frontend/src/components/plugins/previews/index.tsx +83 -0
- package/package.json +4 -1
- package/plugins/creative-search/README.md +26 -0
- package/plugins/creative-search/cli.mjs +421 -0
- package/plugins/creative-search/config.mjs +103 -0
- package/plugins/creative-search/generator.mjs +44 -0
- package/plugins/creative-search/plugin.json +59 -0
- package/plugins/creative-search/ui/DESIGN.md +50 -0
- package/plugins/creative-search/ui/csearch-main.js +311 -0
- package/plugins/creative-search/ui/csearch-settings.js +392 -0
- package/plugins/creative-search/ui/index.js +2 -0
- package/plugins/creative-search/ui/tokens.css +34 -0
- package/plugins/dsh/README.md +20 -0
- package/plugins/dsh/cli.mjs +232 -0
- package/plugins/dsh/generator.mjs +65 -0
- package/plugins/dsh/plugin.json +57 -0
- package/plugins/dsh/ui/DESIGN.md +48 -0
- package/plugins/dsh/ui/dsh-main.js +226 -0
- package/plugins/dsh/ui/dsh-status.js +265 -0
- package/plugins/dsh/ui/index.js +2 -0
- package/plugins/dsh/ui/tokens.css +32 -0
- package/plugins/git-sentinel/README.md +2 -0
- package/plugins/operator-alerts/README.md +9 -4
- package/plugins/operator-alerts/notify-core.mjs +26 -3
- package/plugins/system-monitor/README.md +2 -0
- package/scaffold/.agent/skills/start/SKILL.md +75 -0
- package/scaffold/.agent/skills/start/evals/evals.json +25 -0
- package/scaffold/.agent/skills/start/evals/resolve-startup-entry.test.mjs +17 -0
- package/scaffold/.agent/skills/start/references/runtime-contract.md +9 -0
- package/scaffold/.agent/skills/start/references/startup-check-registration.mjs +14 -0
- package/scaffold/.agent/skills/start/scripts/resolve-startup-entry.mjs +39 -0
- package/scaffold/.agent/skills/start/scripts/start-session.mjs +28 -0
- package/scaffold/.agent/skills/start/subagents/runtime-review.md +3 -0
- package/scaffold/.agent/skills/total-recall/SKILL.md +31 -664
- package/scaffold/.agent/skills/total-recall/references/operations.md +671 -0
- package/src/cli/brief.mjs +5 -1
- package/src/cli/command.mjs +44 -2
- package/src/cli/context.mjs +35 -0
- package/src/cli/doctor.mjs +24 -1
- package/src/cli/help.mjs +2 -1
- package/src/cli/mesh.mjs +15 -1
- package/src/cli/plugin/install.mjs +6 -1
- package/src/cli/plugin/remove.mjs +5 -1
- package/src/cli/recall.mjs +22 -4
- package/src/cli/repo-expert-generate.mjs +35 -2
- package/src/cli/skill.mjs +6 -0
- package/src/cli/startup.mjs +41 -0
- package/src/cli/status.mjs +2 -1
- package/src/core/command-surface.mjs +13 -1
- package/src/core/context-compiler.mjs +42 -311
- package/src/core/context-policy.mjs +59 -0
- package/src/core/env-import.mjs +4 -7
- package/src/core/fast-recall.mjs +130 -70
- package/src/core/memory-layers.mjs +2 -0
- package/src/core/mesh.mjs +34 -7
- package/src/core/skills-registry.mjs +113 -21
- package/src/core/startup-health.mjs +174 -0
- package/src/core/surface.mjs +40 -227
- package/src/server/route-manifest.json +12 -0
- package/src/server/routes/_shared.mjs +5 -2
- package/src/server/routes/context.mjs +17 -3
- package/src/server/routes/instructions.mjs +5 -4
- package/src/server/routes/plugins.mjs +137 -1
- package/frontend/dist/assets/index-BUEZPLim.js +0 -5742
- package/frontend/dist/assets/index-FOJG4jQh.js +0 -5742
package/frontend/dist/index.html
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
18
18
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
19
19
|
<title>Total Recall — Portable Memory</title>
|
|
20
|
-
<script type="module" crossorigin src="/assets/index-
|
|
20
|
+
<script type="module" crossorigin src="/assets/index-BPrkIYkZ.js"></script>
|
|
21
21
|
<link rel="stylesheet" crossorigin href="/assets/index-C7_Xpk27.css">
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
package/frontend/src/App.tsx
CHANGED
|
@@ -95,11 +95,15 @@ function Sidebar({ onLogout, health, activeBrainId, onBrainChange }: SidebarProp
|
|
|
95
95
|
|
|
96
96
|
return (
|
|
97
97
|
<aside className="sidebar">
|
|
98
|
-
<div className="sidebar-brand">
|
|
99
|
-
<
|
|
100
|
-
|
|
98
|
+
<div className="sidebar-brand" style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '16px 14px' }}>
|
|
99
|
+
<BrandMark animated height={44} alt="Total Recall" />
|
|
100
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
101
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
102
|
+
<span style={{ fontSize: 15, fontWeight: 700, letterSpacing: '-0.02em', color: '#f8fafc' }}>Total Recall</span>
|
|
103
|
+
<span style={{ fontSize: 10, fontWeight: 600, padding: '2px 5px', borderRadius: 4, background: 'rgba(59,130,246,0.15)', color: '#60a5fa', border: '1px solid rgba(59,130,246,0.3)' }}>v3.32</span>
|
|
104
|
+
</div>
|
|
105
|
+
<span style={{ fontSize: 11, color: 'var(--text-tertiary)', letterSpacing: '0.01em' }}>Portable memory · any IDE</span>
|
|
101
106
|
</div>
|
|
102
|
-
<span style={{ paddingLeft: 2 }}>Portable memory · any IDE</span>
|
|
103
107
|
</div>
|
|
104
108
|
<nav className="sidebar-nav">
|
|
105
109
|
<div className="nav-section-label">Memory</div>
|
|
@@ -197,3 +197,83 @@ export async function fetchPluginReadme(id: string): Promise<string> {
|
|
|
197
197
|
return ""
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
|
+
|
|
201
|
+
// ── Reviews ─────────────────────────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
export interface PluginReview {
|
|
204
|
+
type: string
|
|
205
|
+
plugin_id: string
|
|
206
|
+
rating: number
|
|
207
|
+
reviewer_node: string
|
|
208
|
+
verified_conformance: boolean
|
|
209
|
+
timestamp: string
|
|
210
|
+
content: string
|
|
211
|
+
_file: string
|
|
212
|
+
portability?: string
|
|
213
|
+
tags?: string[]
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface ReviewsResponse {
|
|
217
|
+
success: boolean
|
|
218
|
+
pluginId: string
|
|
219
|
+
count: number
|
|
220
|
+
averageRating: number | null
|
|
221
|
+
reviews: PluginReview[]
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export async function fetchPluginReviews(id: string, minRating?: number): Promise<ReviewsResponse> {
|
|
225
|
+
try {
|
|
226
|
+
let url = `${API_BASE}/api/plugins/${encodeURIComponent(id)}/reviews`
|
|
227
|
+
if (minRating !== undefined && minRating > 0) {
|
|
228
|
+
url += `?min_rating=${minRating}`
|
|
229
|
+
}
|
|
230
|
+
const res = await apiFetch(url)
|
|
231
|
+
if (!res.ok) return { success: false, pluginId: id, count: 0, averageRating: null, reviews: [] }
|
|
232
|
+
const data = await readJson(res)
|
|
233
|
+
return {
|
|
234
|
+
success: true,
|
|
235
|
+
pluginId: data.pluginId,
|
|
236
|
+
count: data.count,
|
|
237
|
+
averageRating: data.averageRating,
|
|
238
|
+
reviews: Array.isArray(data.reviews) ? data.reviews : [],
|
|
239
|
+
}
|
|
240
|
+
} catch {
|
|
241
|
+
return { success: false, pluginId: id, count: 0, averageRating: null, reviews: [] }
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function submitPluginReview(id: string, options: {
|
|
246
|
+
rating: number
|
|
247
|
+
text: string
|
|
248
|
+
reviewer_node?: string
|
|
249
|
+
verified_conformance?: boolean
|
|
250
|
+
}): Promise<Result> {
|
|
251
|
+
return post(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/reviews`, options)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ── Conformance ──────────────────────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
export interface ConformanceResponse {
|
|
257
|
+
success: boolean
|
|
258
|
+
pluginId: string
|
|
259
|
+
ssss_version: string
|
|
260
|
+
ssss_conformant: boolean
|
|
261
|
+
white_label_verified: boolean
|
|
262
|
+
tested: boolean
|
|
263
|
+
test_count: number
|
|
264
|
+
test_pass_count: number
|
|
265
|
+
test_pass_rate: number | null
|
|
266
|
+
capabilities: string[]
|
|
267
|
+
portability: string
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export async function fetchPluginConformance(id: string): Promise<ConformanceResponse | null> {
|
|
271
|
+
try {
|
|
272
|
+
const res = await apiFetch(`${API_BASE}/api/plugins/${encodeURIComponent(id)}/conformance`)
|
|
273
|
+
if (!res.ok) return null
|
|
274
|
+
const data = await readJson(res)
|
|
275
|
+
return data.success ? data : null
|
|
276
|
+
} catch {
|
|
277
|
+
return null
|
|
278
|
+
}
|
|
279
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react'
|
|
2
|
+
|
|
3
|
+
interface AnimatedBrandMarkProps {
|
|
4
|
+
size?: number
|
|
5
|
+
className?: string
|
|
6
|
+
alt?: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function AnimatedBrandMark({
|
|
10
|
+
size = 42,
|
|
11
|
+
className = '',
|
|
12
|
+
alt = 'Total Recall Animated Mark',
|
|
13
|
+
}: AnimatedBrandMarkProps) {
|
|
14
|
+
const containerStyle: CSSProperties = {
|
|
15
|
+
width: size,
|
|
16
|
+
height: size,
|
|
17
|
+
display: 'inline-flex',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
justifyContent: 'center',
|
|
20
|
+
position: 'relative',
|
|
21
|
+
perspective: 800,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={`animated-brand-mark ${className}`} style={containerStyle} title={alt}>
|
|
26
|
+
<svg
|
|
27
|
+
viewBox="0 0 100 100"
|
|
28
|
+
width={size}
|
|
29
|
+
height={size}
|
|
30
|
+
fill="none"
|
|
31
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
32
|
+
style={{ overflow: 'visible' }}
|
|
33
|
+
>
|
|
34
|
+
<defs>
|
|
35
|
+
{/* Radial glow filter for high-end glass look */}
|
|
36
|
+
<filter id="tr-glow" x="-20%" y="-20%" width="140%" height="140%">
|
|
37
|
+
<feGaussianBlur stdDeviation="3" result="blur" />
|
|
38
|
+
<feComposite in="SourceGraphic" in2="blur" operator="over" />
|
|
39
|
+
</filter>
|
|
40
|
+
|
|
41
|
+
<linearGradient id="tr-top-facet" x1="50" y1="20" x2="80" y2="40" gradientUnits="userSpaceOnUse">
|
|
42
|
+
<stop offset="0%" stopColor="#60a5fa" stopOpacity="0.95" />
|
|
43
|
+
<stop offset="100%" stopColor="#3b82f6" stopOpacity="0.8" />
|
|
44
|
+
</linearGradient>
|
|
45
|
+
|
|
46
|
+
<linearGradient id="tr-left-facet" x1="20" y1="38" x2="50" y2="80" gradientUnits="userSpaceOnUse">
|
|
47
|
+
<stop offset="0%" stopColor="#2563eb" stopOpacity="0.9" />
|
|
48
|
+
<stop offset="100%" stopColor="#1e3a8a" stopOpacity="0.85" />
|
|
49
|
+
</linearGradient>
|
|
50
|
+
|
|
51
|
+
<linearGradient id="tr-right-facet" x1="80" y1="38" x2="50" y2="80" gradientUnits="userSpaceOnUse">
|
|
52
|
+
<stop offset="0%" stopColor="#3b82f6" stopOpacity="0.85" />
|
|
53
|
+
<stop offset="100%" stopColor="#1d4ed8" stopOpacity="0.95" />
|
|
54
|
+
</linearGradient>
|
|
55
|
+
|
|
56
|
+
<linearGradient id="tr-orbit-ring" x1="10" y1="50" x2="90" y2="50" gradientUnits="userSpaceOnUse">
|
|
57
|
+
<stop offset="0%" stopColor="#38bdf8" stopOpacity="0.1" />
|
|
58
|
+
<stop offset="50%" stopColor="#60a5fa" stopOpacity="0.7" />
|
|
59
|
+
<stop offset="100%" stopColor="#818cf8" stopOpacity="0.1" />
|
|
60
|
+
</linearGradient>
|
|
61
|
+
</defs>
|
|
62
|
+
|
|
63
|
+
<style>{`
|
|
64
|
+
@keyframes tr-float {
|
|
65
|
+
0%, 100% {
|
|
66
|
+
transform: translateY(0px) rotate(0deg);
|
|
67
|
+
}
|
|
68
|
+
50% {
|
|
69
|
+
transform: translateY(-3px) rotate(1deg);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@keyframes tr-orbit {
|
|
74
|
+
0% {
|
|
75
|
+
transform: rotateX(68deg) rotateZ(0deg);
|
|
76
|
+
}
|
|
77
|
+
100% {
|
|
78
|
+
transform: rotateX(68deg) rotateZ(360deg);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@keyframes tr-pulse {
|
|
83
|
+
0%, 100% {
|
|
84
|
+
opacity: 0.6;
|
|
85
|
+
transform: scale(0.96);
|
|
86
|
+
}
|
|
87
|
+
50% {
|
|
88
|
+
opacity: 1;
|
|
89
|
+
transform: scale(1.04);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.tr-cube-group {
|
|
94
|
+
transform-origin: 50px 50px;
|
|
95
|
+
animation: tr-float 4.5s ease-in-out infinite;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.tr-orbit-plane {
|
|
99
|
+
transform-origin: 50px 50px;
|
|
100
|
+
animation: tr-orbit 7s linear infinite;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.tr-inner-core {
|
|
104
|
+
transform-origin: 50px 50px;
|
|
105
|
+
animation: tr-pulse 3s ease-in-out infinite;
|
|
106
|
+
}
|
|
107
|
+
`}</style>
|
|
108
|
+
|
|
109
|
+
{/* Orbit ring rotating in 3D perspective */}
|
|
110
|
+
<g className="tr-orbit-plane">
|
|
111
|
+
<ellipse
|
|
112
|
+
cx="50"
|
|
113
|
+
cy="50"
|
|
114
|
+
rx="42"
|
|
115
|
+
ry="42"
|
|
116
|
+
stroke="url(#tr-orbit-ring)"
|
|
117
|
+
strokeWidth="1.5"
|
|
118
|
+
strokeDasharray="16 8"
|
|
119
|
+
/>
|
|
120
|
+
{/* Orbiting glowing memory node */}
|
|
121
|
+
<circle cx="92" cy="50" r="3.5" fill="#38bdf8" filter="url(#tr-glow)" />
|
|
122
|
+
<circle cx="92" cy="50" r="1.8" fill="#ffffff" />
|
|
123
|
+
</g>
|
|
124
|
+
|
|
125
|
+
{/* Floating isometric memory cube */}
|
|
126
|
+
<g className="tr-cube-group">
|
|
127
|
+
{/* Top Facet */}
|
|
128
|
+
<polygon
|
|
129
|
+
points="50,22 80,38 50,54 20,38"
|
|
130
|
+
fill="url(#tr-top-facet)"
|
|
131
|
+
stroke="rgba(255,255,255,0.25)"
|
|
132
|
+
strokeWidth="0.8"
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
{/* Left Facet */}
|
|
136
|
+
<polygon
|
|
137
|
+
points="20,38 50,54 50,86 20,70"
|
|
138
|
+
fill="url(#tr-left-facet)"
|
|
139
|
+
stroke="rgba(255,255,255,0.15)"
|
|
140
|
+
strokeWidth="0.8"
|
|
141
|
+
/>
|
|
142
|
+
|
|
143
|
+
{/* Right Facet */}
|
|
144
|
+
<polygon
|
|
145
|
+
points="50,54 80,38 80,70 50,86"
|
|
146
|
+
fill="url(#tr-right-facet)"
|
|
147
|
+
stroke="rgba(255,255,255,0.15)"
|
|
148
|
+
strokeWidth="0.8"
|
|
149
|
+
/>
|
|
150
|
+
|
|
151
|
+
{/* Glowing central core node */}
|
|
152
|
+
<g className="tr-inner-core">
|
|
153
|
+
<polygon
|
|
154
|
+
points="50,42 62,49 50,56 38,49"
|
|
155
|
+
fill="rgba(147, 197, 253, 0.4)"
|
|
156
|
+
/>
|
|
157
|
+
<circle cx="50" cy="49" r="2.5" fill="#ffffff" filter="url(#tr-glow)" />
|
|
158
|
+
</g>
|
|
159
|
+
</g>
|
|
160
|
+
</svg>
|
|
161
|
+
</div>
|
|
162
|
+
)
|
|
163
|
+
}
|
|
@@ -47,10 +47,10 @@ describe('BrandMark', () => {
|
|
|
47
47
|
expect(screen.getByAltText('Custom Alt')).toBeInTheDocument();
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
it('
|
|
51
|
-
render(<BrandMark
|
|
52
|
-
const
|
|
53
|
-
expect(
|
|
50
|
+
it('renders animated variant when animated=true', () => {
|
|
51
|
+
render(<BrandMark animated height={44} />);
|
|
52
|
+
const animatedEl = document.querySelector('.animated-brand-mark');
|
|
53
|
+
expect(animatedEl).toBeInTheDocument();
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import AnimatedBrandMark from './AnimatedBrandMark'
|
|
2
2
|
|
|
3
|
-
export type BrandVariant = 'lockup' | 'icon' | 'badge' | 'mark'
|
|
3
|
+
export type BrandVariant = 'lockup' | 'icon' | 'badge' | 'mark' | 'animated'
|
|
4
4
|
|
|
5
5
|
interface BrandMarkProps {
|
|
6
6
|
variant?: BrandVariant
|
|
@@ -10,22 +10,31 @@ interface BrandMarkProps {
|
|
|
10
10
|
alt?: string
|
|
11
11
|
/** Light plate behind lockup for dark surfaces (PNG has white bg). */
|
|
12
12
|
plate?: boolean
|
|
13
|
+
/** Render dynamic looping 3D vector animation mark. */
|
|
14
|
+
animated?: boolean
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
const SRC: Record<BrandVariant, string> = {
|
|
17
|
+
const SRC: Record<Exclude<BrandVariant, 'animated'>, string> = {
|
|
16
18
|
lockup: '/brand/total-recall-lockup.png',
|
|
17
19
|
icon: '/brand/total-recall-icon.svg',
|
|
18
20
|
badge: '/brand/total-recall-badge.jpg',
|
|
19
21
|
mark: '/brand/total-recall-mark.svg',
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
export { AnimatedBrandMark }
|
|
25
|
+
|
|
22
26
|
export default function BrandMark({
|
|
23
27
|
variant = 'lockup',
|
|
24
28
|
height = 40,
|
|
25
29
|
className = '',
|
|
26
30
|
alt = 'Total Recall',
|
|
27
31
|
plate = false,
|
|
32
|
+
animated = false,
|
|
28
33
|
}: BrandMarkProps) {
|
|
34
|
+
if (animated || variant === 'animated') {
|
|
35
|
+
return <AnimatedBrandMark size={height} className={className} alt={alt} />
|
|
36
|
+
}
|
|
37
|
+
|
|
29
38
|
const isSquare = variant === 'icon' || variant === 'badge' || variant === 'mark'
|
|
30
39
|
const img = (
|
|
31
40
|
<img
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { type CSSProperties } from "react"
|
|
2
|
+
|
|
3
|
+
const styles: Record<string, CSSProperties> = {
|
|
4
|
+
container: {
|
|
5
|
+
background: "linear-gradient(135deg, #0a1628, #1a1a2e)",
|
|
6
|
+
borderRadius: "12px",
|
|
7
|
+
padding: "24px",
|
|
8
|
+
fontFamily: "var(--font-mono, 'SF Mono', monospace)",
|
|
9
|
+
color: "#e0e0e0",
|
|
10
|
+
maxWidth: "580px",
|
|
11
|
+
},
|
|
12
|
+
header: {
|
|
13
|
+
display: "flex",
|
|
14
|
+
justifyContent: "space-between",
|
|
15
|
+
marginBottom: "16px",
|
|
16
|
+
},
|
|
17
|
+
label: {
|
|
18
|
+
color: "#888",
|
|
19
|
+
fontSize: "11px",
|
|
20
|
+
textTransform: "uppercase" as const,
|
|
21
|
+
letterSpacing: "1px",
|
|
22
|
+
},
|
|
23
|
+
badge: {
|
|
24
|
+
background: "#1a2a1a",
|
|
25
|
+
color: "#4caf50",
|
|
26
|
+
padding: "4px 10px",
|
|
27
|
+
borderRadius: "20px",
|
|
28
|
+
fontSize: "11px",
|
|
29
|
+
},
|
|
30
|
+
summary: {
|
|
31
|
+
display: "flex",
|
|
32
|
+
gap: "16px",
|
|
33
|
+
marginBottom: "16px",
|
|
34
|
+
},
|
|
35
|
+
statCard: {
|
|
36
|
+
background: "#0d1117",
|
|
37
|
+
border: "1px solid #2a2a4a",
|
|
38
|
+
borderRadius: "8px",
|
|
39
|
+
padding: "12px 16px",
|
|
40
|
+
flex: 1,
|
|
41
|
+
},
|
|
42
|
+
statValue: {
|
|
43
|
+
fontSize: "20px",
|
|
44
|
+
fontWeight: 700,
|
|
45
|
+
},
|
|
46
|
+
statLabel: {
|
|
47
|
+
fontSize: "10px",
|
|
48
|
+
color: "#888",
|
|
49
|
+
textTransform: "uppercase" as const,
|
|
50
|
+
letterSpacing: "1px",
|
|
51
|
+
marginTop: "4px",
|
|
52
|
+
},
|
|
53
|
+
gateTable: {
|
|
54
|
+
width: "100%",
|
|
55
|
+
borderCollapse: "collapse" as const,
|
|
56
|
+
},
|
|
57
|
+
th: {
|
|
58
|
+
color: "#888",
|
|
59
|
+
fontSize: "11px",
|
|
60
|
+
textTransform: "uppercase" as const,
|
|
61
|
+
padding: "8px 12px",
|
|
62
|
+
textAlign: "left" as const,
|
|
63
|
+
borderBottom: "1px solid #2a2a4a",
|
|
64
|
+
},
|
|
65
|
+
td: {
|
|
66
|
+
padding: "10px 12px",
|
|
67
|
+
fontSize: "12px",
|
|
68
|
+
borderBottom: "1px solid #1a1a2e",
|
|
69
|
+
},
|
|
70
|
+
pass: {
|
|
71
|
+
color: "#4caf50",
|
|
72
|
+
},
|
|
73
|
+
fail: {
|
|
74
|
+
color: "#ff5252",
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const gates = [
|
|
79
|
+
{ name: "TypeScript", status: "pass", detail: "0 errors" },
|
|
80
|
+
{ name: "ESLint", status: "pass", detail: "0 warnings" },
|
|
81
|
+
{ name: "Vitest", status: "pass", detail: "42/42 tests" },
|
|
82
|
+
{ name: "Bundle Size", status: "pass", detail: "12.4 kB" },
|
|
83
|
+
{ name: "SSSS Schema", status: "fail", detail: "1 warning" },
|
|
84
|
+
{ name: "Mesh Sync", status: "pass", detail: "2 peers synced" },
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
export function CodeQualityPreview() {
|
|
88
|
+
return (
|
|
89
|
+
<div style={styles.container}>
|
|
90
|
+
<div style={styles.header}>
|
|
91
|
+
<span style={styles.label}>Gate Report</span>
|
|
92
|
+
<span style={styles.badge}>5/6 passing</span>
|
|
93
|
+
</div>
|
|
94
|
+
<div style={styles.summary}>
|
|
95
|
+
<div style={{ ...styles.statCard, borderColor: "#1a3a1a" }}>
|
|
96
|
+
<div style={{ ...styles.statValue, color: "#4caf50" }}>5</div>
|
|
97
|
+
<div style={styles.statLabel}>Passing</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div style={styles.statCard}>
|
|
100
|
+
<div style={{ ...styles.statValue, color: "#ff5252" }}>1</div>
|
|
101
|
+
<div style={styles.statLabel}>Failing</div>
|
|
102
|
+
</div>
|
|
103
|
+
<div style={styles.statCard}>
|
|
104
|
+
<div style={{ ...styles.statValue, color: "#64b5f6" }}>6</div>
|
|
105
|
+
<div style={styles.statLabel}>Total Gates</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
<table style={styles.gateTable}>
|
|
109
|
+
<thead>
|
|
110
|
+
<tr>
|
|
111
|
+
<th style={styles.th}>Gate</th>
|
|
112
|
+
<th style={styles.th}>Status</th>
|
|
113
|
+
<th style={styles.th}>Detail</th>
|
|
114
|
+
</tr>
|
|
115
|
+
</thead>
|
|
116
|
+
<tbody>
|
|
117
|
+
{gates.map((g, i) => (
|
|
118
|
+
<tr key={i}>
|
|
119
|
+
<td style={styles.td}>{g.name}</td>
|
|
120
|
+
<td style={{ ...styles.td, ...(g.status === "pass" ? styles.pass : styles.fail) }}>
|
|
121
|
+
{g.status === "pass" ? "✓" : "✗"}
|
|
122
|
+
</td>
|
|
123
|
+
<td style={styles.td}>{g.detail}</td>
|
|
124
|
+
</tr>
|
|
125
|
+
))}
|
|
126
|
+
</tbody>
|
|
127
|
+
</table>
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { useState, type CSSProperties } from "react"
|
|
2
|
+
|
|
3
|
+
const styles: Record<string, CSSProperties> = {
|
|
4
|
+
container: {
|
|
5
|
+
background: "linear-gradient(135deg, #0d1117, #1a1a2e)",
|
|
6
|
+
borderRadius: "12px",
|
|
7
|
+
padding: "24px",
|
|
8
|
+
fontFamily: "var(--font-mono, 'SF Mono', 'Fira Code', monospace)",
|
|
9
|
+
color: "#e0e0e0",
|
|
10
|
+
maxWidth: "520px",
|
|
11
|
+
},
|
|
12
|
+
header: {
|
|
13
|
+
display: "flex",
|
|
14
|
+
justifyContent: "space-between",
|
|
15
|
+
marginBottom: "16px",
|
|
16
|
+
},
|
|
17
|
+
label: {
|
|
18
|
+
color: "#888",
|
|
19
|
+
fontSize: "11px",
|
|
20
|
+
textTransform: "uppercase" as const,
|
|
21
|
+
letterSpacing: "1px",
|
|
22
|
+
},
|
|
23
|
+
badge: {
|
|
24
|
+
background: "#1a2a3a",
|
|
25
|
+
color: "#64b5f6",
|
|
26
|
+
padding: "4px 10px",
|
|
27
|
+
borderRadius: "20px",
|
|
28
|
+
fontSize: "11px",
|
|
29
|
+
},
|
|
30
|
+
terminal: {
|
|
31
|
+
background: "#0a0a1a",
|
|
32
|
+
border: "1px solid #2a2a4a",
|
|
33
|
+
borderRadius: "8px",
|
|
34
|
+
padding: "12px",
|
|
35
|
+
marginBottom: "12px",
|
|
36
|
+
minHeight: "100px",
|
|
37
|
+
overflow: "auto" as const,
|
|
38
|
+
},
|
|
39
|
+
line: {
|
|
40
|
+
fontSize: "12px",
|
|
41
|
+
lineHeight: 1.6,
|
|
42
|
+
whiteSpace: "pre-wrap" as const,
|
|
43
|
+
},
|
|
44
|
+
prompt: {
|
|
45
|
+
color: "#4caf50",
|
|
46
|
+
},
|
|
47
|
+
cmd: {
|
|
48
|
+
color: "#e0e0e0",
|
|
49
|
+
},
|
|
50
|
+
output: {
|
|
51
|
+
color: "#888",
|
|
52
|
+
},
|
|
53
|
+
inputRow: {
|
|
54
|
+
display: "flex",
|
|
55
|
+
alignItems: "center",
|
|
56
|
+
gap: "6px",
|
|
57
|
+
background: "#0a0a1a",
|
|
58
|
+
border: "1px solid #2a2a4a",
|
|
59
|
+
borderRadius: "8px",
|
|
60
|
+
padding: "8px 12px",
|
|
61
|
+
},
|
|
62
|
+
input: {
|
|
63
|
+
flex: 1,
|
|
64
|
+
background: "transparent",
|
|
65
|
+
border: "none",
|
|
66
|
+
color: "#4caf50",
|
|
67
|
+
fontFamily: "var(--font-mono, 'SF Mono', monospace)",
|
|
68
|
+
fontSize: "12px",
|
|
69
|
+
outline: "none",
|
|
70
|
+
},
|
|
71
|
+
commands: {
|
|
72
|
+
display: "flex",
|
|
73
|
+
flexWrap: "wrap" as const,
|
|
74
|
+
gap: "6px",
|
|
75
|
+
marginTop: "12px",
|
|
76
|
+
},
|
|
77
|
+
cmdChip: {
|
|
78
|
+
background: "#1e1e3a",
|
|
79
|
+
border: "1px solid #2a2a4a",
|
|
80
|
+
borderRadius: "6px",
|
|
81
|
+
padding: "4px 10px",
|
|
82
|
+
fontSize: "11px",
|
|
83
|
+
color: "#aaa",
|
|
84
|
+
cursor: "pointer",
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const initialLines = [
|
|
89
|
+
{ kind: "prompt", text: "total-recall@mesh:~$ " },
|
|
90
|
+
{ kind: "cmd", text: "total-recall --help" },
|
|
91
|
+
{ kind: "output", text: "\nTotal Recall Composable CLI v2.1.0" },
|
|
92
|
+
{ kind: "output", text: "\nCommands:" },
|
|
93
|
+
{ kind: "output", text: "\n recall <query> Search memory" },
|
|
94
|
+
{ kind: "output", text: "\n remember <category> Write memory" },
|
|
95
|
+
{ kind: "output", text: "\n compile Rebuild surfaces" },
|
|
96
|
+
{ kind: "output", text: "\n mesh nodes List mesh peers" },
|
|
97
|
+
{ kind: "output", text: "\n plugin list Show installed plugins" },
|
|
98
|
+
{ kind: "output", text: "\n vercel-rotate Rotate API token" },
|
|
99
|
+
{ kind: "prompt", text: "\ntotal-recall@mesh:~$ " },
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
export function ComposableCliPreview() {
|
|
103
|
+
const [cmdHistory, _setCmdHistory] = useState(initialLines)
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div style={styles.container}>
|
|
107
|
+
<div style={styles.header}>
|
|
108
|
+
<span style={styles.label}>Composable CLI</span>
|
|
109
|
+
<span style={styles.badge}>Active</span>
|
|
110
|
+
</div>
|
|
111
|
+
<div style={styles.terminal}>
|
|
112
|
+
{cmdHistory.map((l, i) => (
|
|
113
|
+
<div key={i} style={styles.line}>
|
|
114
|
+
{l.kind === "prompt" && <span style={styles.prompt}>{l.text}</span>}
|
|
115
|
+
{l.kind === "cmd" && <span style={styles.cmd}>{l.text}</span>}
|
|
116
|
+
{l.kind === "output" && <span style={styles.output}>{l.text}</span>}
|
|
117
|
+
</div>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
120
|
+
<div style={styles.inputRow}>
|
|
121
|
+
<span style={{ ...styles.prompt, fontSize: "12px" }}>$</span>
|
|
122
|
+
<input style={styles.input} placeholder="Type a command..." readOnly />
|
|
123
|
+
</div>
|
|
124
|
+
<div style={styles.commands}>
|
|
125
|
+
{["help", "recall", "remember", "compile", "mesh", "plugins"].map((c) => (
|
|
126
|
+
<span key={c} style={styles.cmdChip}>{c}</span>
|
|
127
|
+
))}
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
131
|
+
}
|