total-recall-brain 3.40.3 → 3.40.5
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/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +2 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +26 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +111 -7
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +5 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/agent-login.mjs +127 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-api-rotation.mjs +140 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-catalog.mjs +31 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-rotation-recipes.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-gateway.mjs +21 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-rotate.mjs +40 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-sync.mjs +9 -12
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +8 -7
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +8 -7
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +13 -13
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +340 -164
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +6 -5
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +8 -2
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +295 -178
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/LICENSE +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +8 -7
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +302 -168
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +9 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +8 -5
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/card.js +444 -27
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +124 -1404
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +9 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +0 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +313 -134
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +8 -7
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +1 -3
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +287 -12
- package/src/core/brain-updates.mjs +4 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/test-support/memory-root.mjs +0 -14
|
@@ -1,28 +1,95 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Git Hygiene — Repository Hygiene &
|
|
3
|
-
*
|
|
2
|
+
* Git Hygiene — Repository Hygiene, Worktree Integrity & Stash Tracker
|
|
3
|
+
* Purpose-built domain interface: queries git audit on mount,
|
|
4
|
+
* exposes unstaged diff inspection, upstream synchronization, and branch hygiene.
|
|
4
5
|
*
|
|
6
|
+
* Adheres strictly to invariant: Always push everything, maintain pristine worktrees.
|
|
5
7
|
* Zero emojis, authentic commercial brand identity, touch-first ergonomics (>=44px).
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
10
|
export class GitSentinelCard extends HTMLElement {
|
|
9
11
|
constructor() {
|
|
10
12
|
super();
|
|
11
|
-
this.status = 'Ready';
|
|
12
13
|
this.executing = false;
|
|
14
|
+
this.telemetry = {
|
|
15
|
+
branch: 'main',
|
|
16
|
+
worktree: 'Inspecting...',
|
|
17
|
+
upstream: 'Checking Sync'
|
|
18
|
+
};
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
connectedCallback() {
|
|
16
|
-
this.attachShadow({ mode: 'open' });
|
|
22
|
+
if (!this.shadowRoot) this.attachShadow({ mode: 'open' });
|
|
17
23
|
this.render();
|
|
18
|
-
this.
|
|
24
|
+
this.refreshTelemetry();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async refreshTelemetry() {
|
|
28
|
+
try {
|
|
29
|
+
const res = await this.host?.run('audit', ['--json']);
|
|
30
|
+
let data = null;
|
|
31
|
+
if (typeof res === 'object' && res !== null) {
|
|
32
|
+
data = res.output ? (typeof res.output === 'object' ? res.output : JSON.parse(res.output)) : res;
|
|
33
|
+
} else if (typeof res === 'string') {
|
|
34
|
+
try { data = JSON.parse(res); } catch {}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (data) {
|
|
38
|
+
const branch = data.branch || 'main';
|
|
39
|
+
const isClean = data.worktree?.clean ?? (data.clean ?? false);
|
|
40
|
+
const unstaged = data.worktree?.unstaged ?? 0;
|
|
41
|
+
const staged = data.worktree?.staged ?? 0;
|
|
42
|
+
|
|
43
|
+
let worktreeStatus = 'Clean';
|
|
44
|
+
if (!isClean) {
|
|
45
|
+
const count = unstaged + staged;
|
|
46
|
+
worktreeStatus = count > 0 ? `Dirty (${count} files)` : 'Modified';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const upstream = data.upstream?.status || (data.synced ? 'Synced' : 'Up to date');
|
|
50
|
+
|
|
51
|
+
this.telemetry = {
|
|
52
|
+
branch: branch,
|
|
53
|
+
worktree: worktreeStatus,
|
|
54
|
+
upstream: upstream
|
|
55
|
+
};
|
|
56
|
+
} else {
|
|
57
|
+
this.telemetry = {
|
|
58
|
+
branch: 'main',
|
|
59
|
+
worktree: 'Repository Active',
|
|
60
|
+
upstream: 'Up to date'
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
this.updateView();
|
|
64
|
+
} catch {
|
|
65
|
+
this.telemetry = {
|
|
66
|
+
branch: 'main',
|
|
67
|
+
worktree: 'Inspection Ready',
|
|
68
|
+
upstream: 'Origin Sync'
|
|
69
|
+
};
|
|
70
|
+
this.updateView();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
updateView() {
|
|
75
|
+
const root = this.shadowRoot;
|
|
76
|
+
if (!root) return;
|
|
77
|
+
|
|
78
|
+
const brEl = root.querySelector('#stat-branch');
|
|
79
|
+
const wtEl = root.querySelector('#stat-worktree');
|
|
80
|
+
const upEl = root.querySelector('#stat-upstream');
|
|
81
|
+
if (brEl) brEl.textContent = this.telemetry.branch;
|
|
82
|
+
if (wtEl) wtEl.textContent = this.telemetry.worktree;
|
|
83
|
+
if (upEl) upEl.textContent = this.telemetry.upstream;
|
|
19
84
|
}
|
|
20
85
|
|
|
21
86
|
async execute(action, args = []) {
|
|
22
|
-
const out = this.shadowRoot
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
87
|
+
const out = this.shadowRoot?.querySelector('#card-out');
|
|
88
|
+
const statusPill = this.shadowRoot?.querySelector('#status-pill');
|
|
89
|
+
const actionLabel = action.toUpperCase();
|
|
90
|
+
|
|
91
|
+
if (out) out.textContent = `[SENTINEL AUDITOR] Scanning ${actionLabel} ${args.join(' ')}...`;
|
|
92
|
+
if (statusPill) statusPill.textContent = 'SCANNING';
|
|
26
93
|
this.executing = true;
|
|
27
94
|
|
|
28
95
|
try {
|
|
@@ -34,241 +101,308 @@ export class GitSentinelCard extends HTMLElement {
|
|
|
34
101
|
text = String(res || 'Audit completed without output.');
|
|
35
102
|
}
|
|
36
103
|
if (out) out.textContent = text.trim();
|
|
37
|
-
if (
|
|
104
|
+
if (statusPill) statusPill.textContent = 'SECURE';
|
|
105
|
+
|
|
106
|
+
if (action === 'audit') {
|
|
107
|
+
this.refreshTelemetry();
|
|
108
|
+
}
|
|
38
109
|
} catch (err) {
|
|
39
110
|
if (out) out.textContent = `[SENTINEL ALERT] ${err.message}`;
|
|
40
|
-
if (
|
|
111
|
+
if (statusPill) statusPill.textContent = 'ALERT';
|
|
41
112
|
} finally {
|
|
42
113
|
this.executing = false;
|
|
43
114
|
}
|
|
44
115
|
}
|
|
45
116
|
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (!ctx) return;
|
|
51
|
-
|
|
52
|
-
let ringR1 = 4;
|
|
53
|
-
let ringR2 = 14;
|
|
54
|
-
let ringR3 = 24;
|
|
55
|
-
|
|
56
|
-
const draw = () => {
|
|
57
|
-
if (!this.isConnected) return;
|
|
58
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
59
|
-
|
|
60
|
-
const cx = canvas.width / 2;
|
|
61
|
-
const cy = canvas.height / 2;
|
|
62
|
-
const maxR = 30;
|
|
63
|
-
|
|
64
|
-
// Draw branch spine
|
|
65
|
-
ctx.strokeStyle = 'rgba(16, 185, 129, 0.2)';
|
|
66
|
-
ctx.lineWidth = 1.5;
|
|
67
|
-
ctx.beginPath();
|
|
68
|
-
ctx.moveTo(cx - 80, cy);
|
|
69
|
-
ctx.lineTo(cx + 80, cy);
|
|
70
|
-
ctx.stroke();
|
|
71
|
-
|
|
72
|
-
// Branch forks
|
|
73
|
-
ctx.beginPath();
|
|
74
|
-
ctx.moveTo(cx - 30, cy);
|
|
75
|
-
ctx.lineTo(cx - 10, cy - 14);
|
|
76
|
-
ctx.lineTo(cx + 40, cy - 14);
|
|
77
|
-
ctx.stroke();
|
|
78
|
-
|
|
79
|
-
// Draw pulse rings from head
|
|
80
|
-
const drawRing = (r) => {
|
|
81
|
-
const alpha = Math.max(0, 1 - (r / maxR));
|
|
82
|
-
ctx.strokeStyle = this.executing ? `rgba(52, 211, 153, ${alpha})` : `rgba(16, 185, 129, ${alpha})`;
|
|
83
|
-
ctx.lineWidth = 1.5;
|
|
84
|
-
ctx.beginPath();
|
|
85
|
-
ctx.arc(cx, cy, r, 0, Math.PI * 2);
|
|
86
|
-
ctx.stroke();
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
drawRing(ringR1);
|
|
90
|
-
drawRing(ringR2);
|
|
91
|
-
drawRing(ringR3);
|
|
92
|
-
|
|
93
|
-
// Core commit node
|
|
94
|
-
ctx.fillStyle = '#34d399';
|
|
95
|
-
ctx.shadowColor = '#34d399';
|
|
96
|
-
ctx.shadowBlur = 8;
|
|
97
|
-
ctx.beginPath();
|
|
98
|
-
ctx.arc(cx, cy, 4, 0, Math.PI * 2);
|
|
99
|
-
ctx.fill();
|
|
100
|
-
ctx.shadowBlur = 0;
|
|
101
|
-
|
|
102
|
-
const speed = this.executing ? 0.8 : 0.35;
|
|
103
|
-
ringR1 = (ringR1 + speed) % maxR;
|
|
104
|
-
ringR2 = (ringR2 + speed) % maxR;
|
|
105
|
-
ringR3 = (ringR3 + speed) % maxR;
|
|
106
|
-
|
|
107
|
-
requestAnimationFrame(draw);
|
|
108
|
-
};
|
|
117
|
+
copyOutput() {
|
|
118
|
+
const out = this.shadowRoot?.querySelector('#card-out');
|
|
119
|
+
const copyBtn = this.shadowRoot?.querySelector('#btn-copy');
|
|
120
|
+
if (!out) return;
|
|
109
121
|
|
|
110
|
-
|
|
122
|
+
navigator.clipboard?.writeText(out.textContent || '').then(() => {
|
|
123
|
+
if (copyBtn) {
|
|
124
|
+
const prev = copyBtn.textContent;
|
|
125
|
+
copyBtn.textContent = 'COPIED';
|
|
126
|
+
setTimeout(() => { copyBtn.textContent = prev; }, 1600);
|
|
127
|
+
}
|
|
128
|
+
}).catch(() => {});
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
render() {
|
|
114
|
-
this.shadowRoot
|
|
132
|
+
const root = this.shadowRoot;
|
|
133
|
+
if (!root) return;
|
|
134
|
+
|
|
135
|
+
root.innerHTML = `
|
|
115
136
|
<style>
|
|
116
137
|
:host {
|
|
117
138
|
display: block;
|
|
118
|
-
font-family: -apple-system,
|
|
119
|
-
background: #
|
|
120
|
-
color: #
|
|
121
|
-
border-radius:
|
|
122
|
-
border: 1px solid
|
|
123
|
-
|
|
124
|
-
padding: 18px;
|
|
139
|
+
font-family: 'Space Grotesk', -apple-system, sans-serif;
|
|
140
|
+
background: #140d04;
|
|
141
|
+
color: #fef3c7;
|
|
142
|
+
border-radius: 12px;
|
|
143
|
+
border: 1px solid #78350f;
|
|
144
|
+
padding: 14px;
|
|
125
145
|
box-sizing: border-box;
|
|
126
|
-
|
|
146
|
+
user-select: none;
|
|
127
147
|
}
|
|
128
|
-
|
|
148
|
+
|
|
149
|
+
* { box-sizing: border-box; }
|
|
150
|
+
|
|
151
|
+
/* Bespoke Header */
|
|
152
|
+
.card-header {
|
|
129
153
|
display: flex;
|
|
154
|
+
align-items: center;
|
|
130
155
|
justify-content: space-between;
|
|
131
|
-
|
|
132
|
-
|
|
156
|
+
margin-bottom: 12px;
|
|
157
|
+
padding-bottom: 8px;
|
|
158
|
+
border-bottom: 1px solid rgba(245, 158, 11, 0.25);
|
|
133
159
|
}
|
|
160
|
+
|
|
161
|
+
.brand-cluster {
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
gap: 10px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.brand-mark {
|
|
168
|
+
width: 32px;
|
|
169
|
+
height: 32px;
|
|
170
|
+
border-radius: 8px;
|
|
171
|
+
background: rgba(217, 119, 6, 0.2);
|
|
172
|
+
border: 1px solid rgba(245, 158, 11, 0.4);
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
justify-content: center;
|
|
176
|
+
flex-shrink: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
134
179
|
.brand-meta {
|
|
135
180
|
display: flex;
|
|
136
181
|
flex-direction: column;
|
|
137
|
-
gap: 2px;
|
|
138
182
|
}
|
|
139
|
-
|
|
140
|
-
|
|
183
|
+
|
|
184
|
+
.brand-title {
|
|
185
|
+
font-size: 14px;
|
|
141
186
|
font-weight: 700;
|
|
142
|
-
|
|
187
|
+
color: #fef3c7;
|
|
188
|
+
letter-spacing: 0.03em;
|
|
143
189
|
text-transform: uppercase;
|
|
144
|
-
color: #a7f3d0;
|
|
145
190
|
margin: 0;
|
|
146
191
|
}
|
|
147
|
-
|
|
192
|
+
|
|
193
|
+
.brand-subtitle {
|
|
148
194
|
font-size: 11px;
|
|
149
|
-
color: #
|
|
150
|
-
letter-spacing: 0.02em;
|
|
195
|
+
color: #fcd34d;
|
|
151
196
|
margin: 0;
|
|
197
|
+
font-family: 'JetBrains Mono', monospace;
|
|
152
198
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
justify-content: center;
|
|
199
|
+
|
|
200
|
+
.status-pill {
|
|
201
|
+
font-family: 'JetBrains Mono', monospace;
|
|
157
202
|
font-size: 10px;
|
|
158
203
|
font-weight: 700;
|
|
159
|
-
|
|
160
|
-
text-transform: uppercase;
|
|
161
|
-
color: #34d399;
|
|
162
|
-
background: rgba(16, 185, 129, 0.12);
|
|
163
|
-
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
164
|
-
border-radius: 4px;
|
|
165
|
-
padding: 4px 8px;
|
|
166
|
-
}
|
|
167
|
-
.visual-display {
|
|
168
|
-
position: relative;
|
|
169
|
-
background: #020b08;
|
|
170
|
-
border: 1px solid rgba(16, 185, 129, 0.2);
|
|
204
|
+
padding: 3px 8px;
|
|
171
205
|
border-radius: 6px;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
display: block;
|
|
177
|
-
width: 100%;
|
|
178
|
-
height: 64px;
|
|
206
|
+
background: rgba(245, 158, 11, 0.15);
|
|
207
|
+
border: 1px solid rgba(245, 158, 11, 0.4);
|
|
208
|
+
color: #fbbf24;
|
|
209
|
+
letter-spacing: 0.05em;
|
|
179
210
|
}
|
|
211
|
+
|
|
212
|
+
/* Telemetry Metric Cards */
|
|
180
213
|
.telemetry-row {
|
|
181
|
-
display: flex;
|
|
182
|
-
justify-content: space-between;
|
|
183
|
-
padding: 6px 10px;
|
|
184
|
-
background: rgba(255, 255, 255, 0.03);
|
|
185
|
-
border-top: 1px solid rgba(16, 185, 129, 0.15);
|
|
186
|
-
font-family: monospace;
|
|
187
|
-
font-size: 11px;
|
|
188
|
-
color: #6ee7b7;
|
|
189
|
-
}
|
|
190
|
-
.actions-grid {
|
|
191
214
|
display: grid;
|
|
192
215
|
grid-template-columns: repeat(3, 1fr);
|
|
193
216
|
gap: 8px;
|
|
194
217
|
margin-bottom: 12px;
|
|
195
218
|
}
|
|
219
|
+
|
|
220
|
+
.metric-card {
|
|
221
|
+
background: rgba(120, 53, 15, 0.4);
|
|
222
|
+
border: 1px solid rgba(245, 158, 11, 0.25);
|
|
223
|
+
border-radius: 8px;
|
|
224
|
+
padding: 8px 10px;
|
|
225
|
+
display: flex;
|
|
226
|
+
flex-direction: column;
|
|
227
|
+
gap: 2px;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.metric-label {
|
|
231
|
+
font-family: 'JetBrains Mono', monospace;
|
|
232
|
+
font-size: 9px;
|
|
233
|
+
font-weight: 700;
|
|
234
|
+
color: #fcd34d;
|
|
235
|
+
letter-spacing: 0.05em;
|
|
236
|
+
text-transform: uppercase;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.metric-value {
|
|
240
|
+
font-size: 13px;
|
|
241
|
+
font-weight: 700;
|
|
242
|
+
color: #ffffff;
|
|
243
|
+
font-family: 'JetBrains Mono', monospace;
|
|
244
|
+
overflow: hidden;
|
|
245
|
+
text-overflow: ellipsis;
|
|
246
|
+
white-space: nowrap;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* Action Buttons Grid (>=44px touch targets) */
|
|
250
|
+
.actions-grid {
|
|
251
|
+
display: grid;
|
|
252
|
+
grid-template-columns: repeat(4, 1fr);
|
|
253
|
+
gap: 6px;
|
|
254
|
+
margin-bottom: 10px;
|
|
255
|
+
}
|
|
256
|
+
|
|
196
257
|
.touch-btn {
|
|
197
258
|
min-height: 44px;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
border: 1px solid rgba(16, 185, 129, 0.25);
|
|
204
|
-
color: #a7f3d0;
|
|
259
|
+
background: rgba(217, 119, 6, 0.16);
|
|
260
|
+
border: 1px solid rgba(245, 158, 11, 0.3);
|
|
261
|
+
border-radius: 8px;
|
|
262
|
+
color: #fef3c7;
|
|
263
|
+
font-family: 'JetBrains Mono', monospace;
|
|
205
264
|
font-size: 11px;
|
|
206
265
|
font-weight: 600;
|
|
207
|
-
letter-spacing: 0.
|
|
208
|
-
|
|
209
|
-
|
|
266
|
+
letter-spacing: 0.03em;
|
|
267
|
+
display: flex;
|
|
268
|
+
align-items: center;
|
|
269
|
+
justify-content: center;
|
|
210
270
|
cursor: pointer;
|
|
211
|
-
transition: background 0.15s
|
|
212
|
-
padding: 6px
|
|
271
|
+
transition: background 0.15s, border-color 0.15s, transform 0.05s;
|
|
272
|
+
padding: 4px 6px;
|
|
213
273
|
text-align: center;
|
|
214
274
|
}
|
|
275
|
+
|
|
215
276
|
.touch-btn:hover {
|
|
216
|
-
background: rgba(
|
|
217
|
-
border-color: rgba(
|
|
277
|
+
background: rgba(217, 119, 6, 0.3);
|
|
278
|
+
border-color: rgba(251, 191, 36, 0.6);
|
|
218
279
|
}
|
|
280
|
+
|
|
219
281
|
.touch-btn:active {
|
|
220
282
|
transform: translateY(1px);
|
|
221
283
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
284
|
+
|
|
285
|
+
/* Terminal Execution Output */
|
|
286
|
+
.terminal-deck {
|
|
287
|
+
background: #0a0602;
|
|
288
|
+
border: 1px solid rgba(245, 158, 11, 0.25);
|
|
289
|
+
border-radius: 8px;
|
|
290
|
+
overflow: hidden;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.terminal-header {
|
|
294
|
+
display: flex;
|
|
295
|
+
align-items: center;
|
|
296
|
+
justify-content: space-between;
|
|
297
|
+
padding: 6px 10px;
|
|
298
|
+
background: rgba(120, 53, 15, 0.4);
|
|
299
|
+
border-bottom: 1px solid rgba(245, 158, 11, 0.2);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.terminal-title {
|
|
303
|
+
font-family: 'JetBrains Mono', monospace;
|
|
304
|
+
font-size: 10px;
|
|
305
|
+
color: #fcd34d;
|
|
306
|
+
text-transform: uppercase;
|
|
307
|
+
letter-spacing: 0.05em;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.terminal-btn {
|
|
311
|
+
background: rgba(245, 158, 11, 0.15);
|
|
312
|
+
border: 1px solid rgba(245, 158, 11, 0.3);
|
|
313
|
+
border-radius: 4px;
|
|
314
|
+
color: #fef3c7;
|
|
315
|
+
font-family: 'JetBrains Mono', monospace;
|
|
316
|
+
font-size: 9px;
|
|
317
|
+
padding: 2px 6px;
|
|
318
|
+
cursor: pointer;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.terminal-btn:hover {
|
|
322
|
+
background: rgba(245, 158, 11, 0.3);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.terminal-body {
|
|
326
|
+
margin: 0;
|
|
226
327
|
padding: 8px 10px;
|
|
227
|
-
font-family:
|
|
328
|
+
font-family: 'JetBrains Mono', monospace;
|
|
228
329
|
font-size: 11px;
|
|
229
330
|
line-height: 1.45;
|
|
230
|
-
color: #
|
|
231
|
-
min-height:
|
|
232
|
-
max-height:
|
|
331
|
+
color: #fef3c7;
|
|
332
|
+
min-height: 60px;
|
|
333
|
+
max-height: 100px;
|
|
233
334
|
overflow-y: auto;
|
|
234
335
|
white-space: pre-wrap;
|
|
235
336
|
word-break: break-word;
|
|
236
337
|
}
|
|
237
338
|
</style>
|
|
238
339
|
|
|
239
|
-
<div class="header">
|
|
240
|
-
<div class="brand-
|
|
241
|
-
<
|
|
242
|
-
|
|
340
|
+
<div class="card-header">
|
|
341
|
+
<div class="brand-cluster">
|
|
342
|
+
<div class="brand-mark">
|
|
343
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
344
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
|
345
|
+
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
346
|
+
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
347
|
+
</svg>
|
|
348
|
+
</div>
|
|
349
|
+
<div class="brand-meta">
|
|
350
|
+
<h3 class="brand-title">Git Hygiene</h3>
|
|
351
|
+
<span class="brand-subtitle">Sentinel Shield • v1.2.1</span>
|
|
352
|
+
</div>
|
|
243
353
|
</div>
|
|
244
|
-
<div id="status-
|
|
354
|
+
<div id="status-pill" class="status-pill">MONITOR</div>
|
|
245
355
|
</div>
|
|
246
356
|
|
|
247
|
-
<div class="
|
|
248
|
-
<
|
|
249
|
-
|
|
250
|
-
<span>
|
|
251
|
-
|
|
357
|
+
<div class="telemetry-row">
|
|
358
|
+
<div class="metric-card">
|
|
359
|
+
<span class="metric-label">Active Branch</span>
|
|
360
|
+
<span id="stat-branch" class="metric-value">main</span>
|
|
361
|
+
</div>
|
|
362
|
+
<div class="metric-card">
|
|
363
|
+
<span class="metric-label">Worktree</span>
|
|
364
|
+
<span id="stat-worktree" class="metric-value">Inspecting...</span>
|
|
365
|
+
</div>
|
|
366
|
+
<div class="metric-card">
|
|
367
|
+
<span class="metric-label">Upstream</span>
|
|
368
|
+
<span id="stat-upstream" class="metric-value">Checking Sync</span>
|
|
252
369
|
</div>
|
|
253
370
|
</div>
|
|
254
371
|
|
|
255
372
|
<div class="actions-grid">
|
|
256
|
-
<button id="btn-audit" class="touch-btn" type="button">
|
|
257
|
-
<button id="btn-diff" class="touch-btn" type="button">
|
|
258
|
-
<button id="btn-
|
|
373
|
+
<button id="btn-audit" class="touch-btn" type="button">AUDIT</button>
|
|
374
|
+
<button id="btn-diff" class="touch-btn" type="button">DIFFSTAT</button>
|
|
375
|
+
<button id="btn-json" class="touch-btn" type="button">JSON AUDIT</button>
|
|
376
|
+
<button id="btn-refresh" class="touch-btn" type="button">REFRESH</button>
|
|
259
377
|
</div>
|
|
260
378
|
|
|
261
|
-
<div
|
|
379
|
+
<div class="terminal-deck">
|
|
380
|
+
<div class="terminal-header">
|
|
381
|
+
<span class="terminal-title">Worktree Audit Stream</span>
|
|
382
|
+
<button id="btn-copy" class="terminal-btn" type="button">COPY</button>
|
|
383
|
+
</div>
|
|
384
|
+
<pre id="card-out" class="terminal-body">Git worktree sentinel active. Click any action above to inspect hygiene state.</pre>
|
|
385
|
+
</div>
|
|
262
386
|
`;
|
|
263
387
|
|
|
264
|
-
|
|
388
|
+
root.querySelector('#btn-audit')?.addEventListener('click', () => {
|
|
265
389
|
this.execute('audit');
|
|
266
390
|
});
|
|
267
|
-
|
|
391
|
+
|
|
392
|
+
root.querySelector('#btn-diff')?.addEventListener('click', () => {
|
|
268
393
|
this.execute('diff');
|
|
269
394
|
});
|
|
270
|
-
|
|
271
|
-
|
|
395
|
+
|
|
396
|
+
root.querySelector('#btn-json')?.addEventListener('click', () => {
|
|
397
|
+
this.execute('audit', ['--json']);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
root.querySelector('#btn-refresh')?.addEventListener('click', () => {
|
|
401
|
+
this.execute('audit');
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
root.querySelector('#btn-copy')?.addEventListener('click', () => {
|
|
405
|
+
this.copyOutput();
|
|
272
406
|
});
|
|
273
407
|
}
|
|
274
408
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tr-plugin-mesh",
|
|
3
3
|
"version": "0.2.2",
|
|
4
|
-
"private": true,
|
|
5
4
|
"type": "module",
|
|
6
5
|
"description": "Headscale and Tailscale SSH control-server mesh administration and node discovery",
|
|
7
6
|
"scripts": {
|
|
@@ -10,5 +9,13 @@
|
|
|
10
9
|
"license": "MIT",
|
|
11
10
|
"dependencies": {
|
|
12
11
|
"express": "^5.2.1"
|
|
13
|
-
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"cli.mjs",
|
|
15
|
+
"plugin.json",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"ui/",
|
|
19
|
+
"src/"
|
|
20
|
+
]
|
|
14
21
|
}
|
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"card_face": {
|
|
20
|
-
"skin": "
|
|
20
|
+
"skin": "mesh-telemetry",
|
|
21
21
|
"theme": "vibrant",
|
|
22
22
|
"headline": "Mesh Control Deck",
|
|
23
|
+
"primary_color": "#2563eb",
|
|
24
|
+
"secondary_color": "#1e3a8a",
|
|
25
|
+
"accent_color": "#3b82f6",
|
|
23
26
|
"quick_actions": [
|
|
24
27
|
{
|
|
25
28
|
"subcommand": "status",
|
|
@@ -30,12 +33,12 @@
|
|
|
30
33
|
"label": "NODES"
|
|
31
34
|
},
|
|
32
35
|
{
|
|
33
|
-
"subcommand": "
|
|
34
|
-
"label": "
|
|
36
|
+
"subcommand": "doctor",
|
|
37
|
+
"label": "DOCTOR"
|
|
35
38
|
},
|
|
36
39
|
{
|
|
37
|
-
"subcommand": "
|
|
38
|
-
"label": "
|
|
40
|
+
"subcommand": "leader",
|
|
41
|
+
"label": "LEADER"
|
|
39
42
|
}
|
|
40
43
|
],
|
|
41
44
|
"touch_layout": "comfortable",
|