total-recall-brain 3.41.1 → 3.41.3
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/bin/total-recall.mjs +9 -3
- package/frontend/dist/assets/{index-BG9NkVUy.css → index-BIQmqDKP.css} +1 -1
- package/frontend/dist/assets/{index-BtuiZqwP.js → index-DFenQQEQ.js} +74 -79
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/sw.js +8 -5
- package/frontend/src/api/auth.ts +0 -3
- package/frontend/src/components/plugins/PluginPanel.tsx +7 -3
- package/frontend/src/components/plugins/card/CardEngine.tsx +1 -1
- package/frontend/src/pages/LoginPage.tsx +1 -41
- package/frontend/src/pages/PluginsPage.tsx +14 -7
- package/package.json +2 -2
- package/scaffold/.agent/skills/plugin/scripts/record.mjs +6 -3
- package/scaffold/.agent/skills/total-recall/plugins/auth/README.md +10 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/cli.mjs +197 -31
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +1456 -12
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +8 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +210 -27
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-catalog.mjs +10 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/rotation-capability.mjs +15 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-env-export.mjs +78 -6
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-merge.mjs +131 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-remote-deploy.mjs +111 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-store.mjs +26 -5
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/DESIGN.md +56 -8
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +1068 -204
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/panel.js +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/ui/DESIGN.md +32 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/ui/card.js +436 -274
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +16 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +461 -242
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +1 -7
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/DESIGN.md +17 -2
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +426 -300
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/DESIGN.md +32 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +350 -283
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +31 -19
- package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +10 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/{src/core/headscale-server.mjs → capability/control-server.mjs} +5 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/capability/headscale-api.mjs +192 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/capability/index.mjs +46 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +9 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +23 -22
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +6 -3
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +242 -8
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +14 -9
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/server.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/credentials.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/headscale-client.mjs +34 -181
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-auth.mjs +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/presence.mjs +5 -5
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/screen-view.mjs +78 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/DESIGN.md +211 -12
- package/scaffold/.agent/skills/total-recall/plugins/mesh/ui/card.js +323 -388
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +12 -1
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +7 -4
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +34 -1
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/bootstrap.mjs +99 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/README.md +10 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/architecture.md +5 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/ide.md +10 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/memory.md +11 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/secrets.md +7 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/templates/openwiki/skills.md +7 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +16 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +380 -298
- package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +7 -1
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/security/src/scanner.mjs +17 -3
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +38 -15
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +60 -34
- package/scaffold/.agent/skills/total-recall/references/auth.md +2 -0
- package/src/cli/command.mjs +23 -18
- package/src/cli/daemon.mjs +23 -1
- package/src/cli/plugin/copies.mjs +8 -5
- package/src/cli/plugin/index.mjs +25 -2
- package/src/cli/rebuild.mjs +22 -0
- package/src/cli/reset-password.mjs +3 -2
- package/src/cli/skill.mjs +8 -2
- package/src/cli/status.mjs +25 -7
- package/src/core/automatic-brain-updates.mjs +9 -3
- package/src/core/brain-updates.mjs +63 -5
- package/src/core/global-brain-updates.mjs +21 -1
- package/src/core/mesh-brain-updates.mjs +5 -2
- package/src/core/meta-harness.mjs +16 -41
- package/src/core/plugin-runner.mjs +6 -1
- package/src/core/plugin-store.mjs +67 -1
- package/src/core/plugin-updates.mjs +1 -1
- package/src/core/portable-skills-maintenance.mjs +19 -0
- package/src/core/required-plugins.mjs +7 -0
- package/src/core/skills-registry.mjs +33 -3
- package/src/server/auth.mjs +41 -1
- package/src/server/memory-app.mjs +2 -1
- package/src/server/routes/auth.mjs +25 -1
- package/src/server/routes/plugins.mjs +17 -4
|
@@ -1,365 +1,584 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* Purpose-built domain interface: queries latest gate report on mount, displays real
|
|
4
|
-
* deterministic gate findings and stale file tracking, and exposes authentic execution verbs.
|
|
2
|
+
* Nitpicker — Fail-Closed Code Quality Gate Console
|
|
5
3
|
*
|
|
6
|
-
*
|
|
4
|
+
* Bespoke operator interface for deterministic repository verification.
|
|
5
|
+
* Displays real-time gate matrix, structured code violations, tier controllers,
|
|
6
|
+
* and worktree drift indicators with zero template wrappers or terminal dumps.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
const DASH = '\u2014';
|
|
10
|
+
|
|
11
|
+
function escapeHtml(str) {
|
|
12
|
+
if (str === null || str === undefined) return '';
|
|
13
|
+
return String(str).replace(/[&<>"']/g, c => ({
|
|
14
|
+
'&': '&',
|
|
15
|
+
'<': '<',
|
|
16
|
+
'>': '>',
|
|
17
|
+
'"': '"',
|
|
18
|
+
"'": '''
|
|
19
|
+
}[c]));
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
export class CodeQualityCard extends HTMLElement {
|
|
10
23
|
constructor() {
|
|
11
24
|
super();
|
|
25
|
+
this.report = null;
|
|
12
26
|
this.executing = false;
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
27
|
+
this.activeFilter = 'all';
|
|
28
|
+
this.selectedTier = 'fast';
|
|
29
|
+
this.screens = [{ id: 'overview', label: 'Gate Matrix' }];
|
|
30
|
+
this.screen = 'overview';
|
|
18
31
|
}
|
|
19
32
|
|
|
20
33
|
connectedCallback() {
|
|
21
|
-
if (!this.shadowRoot)
|
|
34
|
+
if (!this.shadowRoot) {
|
|
35
|
+
this.attachShadow({ mode: 'open' });
|
|
36
|
+
}
|
|
22
37
|
this.render();
|
|
23
|
-
this.
|
|
38
|
+
this.refreshReport();
|
|
24
39
|
}
|
|
25
40
|
|
|
26
|
-
async
|
|
41
|
+
async refreshReport() {
|
|
42
|
+
if (!this.host) return;
|
|
27
43
|
try {
|
|
28
|
-
const res = await this.host
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
text = String(res || '');
|
|
44
|
+
const res = await this.host.run('report', ['--json']);
|
|
45
|
+
if (res && typeof res === 'object') {
|
|
46
|
+
this.report = res;
|
|
47
|
+
} else if (typeof res === 'string' && res.trim().startsWith('{')) {
|
|
48
|
+
this.report = JSON.parse(res);
|
|
34
49
|
}
|
|
35
|
-
|
|
36
|
-
const isClean = text.includes('0 finding') || text.includes('No findings');
|
|
37
|
-
const isStale = text.includes('STALE');
|
|
38
|
-
|
|
39
|
-
this.telemetry = {
|
|
40
|
-
findings: isClean ? '0 Findings' : 'Findings Detected',
|
|
41
|
-
tier: text.includes('tier=full') ? 'Full Tier' : 'Fast Tier',
|
|
42
|
-
status: isClean ? (isStale ? 'Stale' : 'Pass') : 'Needs Review'
|
|
43
|
-
};
|
|
44
|
-
this.updateView();
|
|
50
|
+
this.render();
|
|
45
51
|
} catch {
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
tier: 'Gate Deck',
|
|
49
|
-
status: 'Ready'
|
|
50
|
-
};
|
|
51
|
-
this.updateView();
|
|
52
|
+
this.report = null;
|
|
53
|
+
this.render();
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!root) return;
|
|
58
|
-
|
|
59
|
-
const findingsEl = root.querySelector('#stat-findings');
|
|
60
|
-
const tierEl = root.querySelector('#stat-tier');
|
|
61
|
-
const statusEl = root.querySelector('#stat-status');
|
|
62
|
-
if (findingsEl) findingsEl.textContent = this.telemetry.findings;
|
|
63
|
-
if (tierEl) tierEl.textContent = this.telemetry.tier;
|
|
64
|
-
if (statusEl) statusEl.textContent = this.telemetry.status;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async execute(action, args = []) {
|
|
68
|
-
const out = this.shadowRoot?.querySelector('#card-out');
|
|
69
|
-
const actionLabel = action.toUpperCase();
|
|
70
|
-
if (out) out.textContent = `[CODE QUALITY] Running ${actionLabel}...`;
|
|
57
|
+
async runTier(tier) {
|
|
58
|
+
if (!this.host || this.executing) return;
|
|
71
59
|
this.executing = true;
|
|
60
|
+
this.selectedTier = tier;
|
|
61
|
+
this.render();
|
|
72
62
|
|
|
73
63
|
try {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
} else {
|
|
79
|
-
text = String(res || 'Execution completed without output.');
|
|
80
|
-
}
|
|
81
|
-
if (out) out.textContent = text.trim();
|
|
82
|
-
if (['gate', 'snapshot', 'report'].includes(action)) {
|
|
83
|
-
this.refreshStatus();
|
|
84
|
-
}
|
|
85
|
-
} catch (err) {
|
|
86
|
-
if (out) out.textContent = `[QUALITY FAILURE] ${err.message}`;
|
|
64
|
+
await this.host.run('check', ['--tier', tier, '--json']);
|
|
65
|
+
await this.refreshReport();
|
|
66
|
+
} catch {
|
|
67
|
+
await this.refreshReport();
|
|
87
68
|
} finally {
|
|
88
69
|
this.executing = false;
|
|
70
|
+
this.render();
|
|
89
71
|
}
|
|
90
72
|
}
|
|
91
73
|
|
|
74
|
+
setFilter(filter) {
|
|
75
|
+
this.activeFilter = filter;
|
|
76
|
+
this.render();
|
|
77
|
+
}
|
|
78
|
+
|
|
92
79
|
render() {
|
|
93
80
|
const root = this.shadowRoot;
|
|
94
81
|
if (!root) return;
|
|
95
82
|
|
|
83
|
+
const rep = this.report;
|
|
84
|
+
const isClean = rep?.clean === true;
|
|
85
|
+
const checks = Array.isArray(rep?.checks) ? rep.checks : [];
|
|
86
|
+
const timestamp = rep?.timestamp ? new Date(rep.timestamp).toLocaleTimeString() : DASH;
|
|
87
|
+
const tierName = rep?.tier || this.selectedTier;
|
|
88
|
+
|
|
89
|
+
// Aggregate findings
|
|
90
|
+
const allFindings = [];
|
|
91
|
+
for (const c of checks) {
|
|
92
|
+
if (Array.isArray(c.findings)) {
|
|
93
|
+
for (const f of c.findings) {
|
|
94
|
+
allFindings.push({ ...f, checkName: c.name || c.id });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const errorCount = allFindings.filter(f => f.severity === 'error').length;
|
|
100
|
+
const warnCount = allFindings.filter(f => f.severity === 'warning').length;
|
|
101
|
+
|
|
102
|
+
const filteredFindings = allFindings.filter(f => {
|
|
103
|
+
if (this.activeFilter === 'errors') return f.severity === 'error';
|
|
104
|
+
if (this.activeFilter === 'warnings') return f.severity === 'warning';
|
|
105
|
+
return true;
|
|
106
|
+
});
|
|
107
|
+
|
|
96
108
|
root.innerHTML = `
|
|
97
109
|
<style>
|
|
98
110
|
:host {
|
|
111
|
+
--face-bg: #0f172a;
|
|
112
|
+
--face-surface: #1e293b;
|
|
113
|
+
--face-line: #334155;
|
|
114
|
+
--face-text: #f8fafc;
|
|
115
|
+
--face-muted: #94a3b8;
|
|
116
|
+
--face-brand: #eab308;
|
|
117
|
+
--face-brand-hover: #facc15;
|
|
118
|
+
--face-accent: #38bdf8;
|
|
119
|
+
--face-ok: #10b981;
|
|
120
|
+
--face-danger: #ef4444;
|
|
121
|
+
--face-warn: #f59e0b;
|
|
122
|
+
--face-dark: #0f172a;
|
|
123
|
+
|
|
99
124
|
display: block;
|
|
100
|
-
font-family:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
border
|
|
104
|
-
border:
|
|
105
|
-
padding:
|
|
125
|
+
font-family: var(--font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
|
|
126
|
+
color: var(--text-primary, var(--face-text));
|
|
127
|
+
background: var(--bg-secondary, var(--face-bg));
|
|
128
|
+
border: 1px solid var(--border, var(--face-line));
|
|
129
|
+
border-radius: 8px;
|
|
130
|
+
padding: 16px;
|
|
106
131
|
box-sizing: border-box;
|
|
107
|
-
|
|
132
|
+
overflow: hidden;
|
|
108
133
|
}
|
|
109
134
|
|
|
110
|
-
|
|
135
|
+
@media (prefers-reduced-motion: reduce) {
|
|
136
|
+
*, ::before, ::after {
|
|
137
|
+
animation-duration: 0.01ms !important;
|
|
138
|
+
animation-iteration-count: 1 !important;
|
|
139
|
+
transition-duration: 0.01ms !important;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
111
142
|
|
|
112
|
-
/*
|
|
113
|
-
.
|
|
114
|
-
display:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
143
|
+
/* Header Bar */
|
|
144
|
+
.header {
|
|
145
|
+
display: flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: space-between;
|
|
148
|
+
flex-wrap: wrap;
|
|
149
|
+
gap: 12px;
|
|
150
|
+
padding-bottom: 14px;
|
|
151
|
+
border-bottom: 1px solid var(--border, var(--face-line));
|
|
152
|
+
margin-bottom: 16px;
|
|
118
153
|
}
|
|
119
154
|
|
|
120
|
-
.
|
|
121
|
-
background: rgba(8, 47, 61, 0.6);
|
|
122
|
-
border: 1px solid rgba(6, 182, 212, 0.25);
|
|
123
|
-
border-radius: 8px;
|
|
124
|
-
padding: 8px 10px;
|
|
155
|
+
.brand-group {
|
|
125
156
|
display: flex;
|
|
126
|
-
|
|
127
|
-
gap:
|
|
157
|
+
align-items: center;
|
|
158
|
+
gap: 10px;
|
|
128
159
|
}
|
|
129
160
|
|
|
130
|
-
.
|
|
131
|
-
font-family: 'JetBrains Mono', monospace;
|
|
132
|
-
font-size:
|
|
133
|
-
font-weight:
|
|
134
|
-
color: #67e8f9;
|
|
161
|
+
.wordmark-badge {
|
|
162
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
163
|
+
font-size: 13px;
|
|
164
|
+
font-weight: 800;
|
|
135
165
|
letter-spacing: 0.05em;
|
|
136
|
-
|
|
166
|
+
color: var(--card-accent, var(--face-accent));
|
|
167
|
+
background: rgba(56, 189, 248, 0.12);
|
|
168
|
+
padding: 6px 10px;
|
|
169
|
+
border-radius: 6px;
|
|
170
|
+
border: 1px solid rgba(56, 189, 248, 0.3);
|
|
137
171
|
}
|
|
138
172
|
|
|
139
|
-
.
|
|
140
|
-
|
|
173
|
+
.title-meta {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-direction: column;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.plugin-title {
|
|
179
|
+
font-size: 14px;
|
|
141
180
|
font-weight: 700;
|
|
142
|
-
color:
|
|
143
|
-
|
|
144
|
-
overflow: hidden;
|
|
145
|
-
text-overflow: ellipsis;
|
|
146
|
-
white-space: nowrap;
|
|
181
|
+
color: var(--text-primary, var(--face-text));
|
|
182
|
+
margin: 0;
|
|
147
183
|
}
|
|
148
184
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
border-radius: 8px;
|
|
154
|
-
padding: 8px 10px;
|
|
155
|
-
margin-bottom: 10px;
|
|
185
|
+
.plugin-subtitle {
|
|
186
|
+
font-size: 11px;
|
|
187
|
+
color: var(--text-secondary, var(--face-muted));
|
|
188
|
+
margin: 0;
|
|
156
189
|
}
|
|
157
190
|
|
|
158
|
-
.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
191
|
+
.verdict-chip {
|
|
192
|
+
display: flex;
|
|
193
|
+
align-items: center;
|
|
194
|
+
gap: 6px;
|
|
195
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
196
|
+
font-size: 11px;
|
|
197
|
+
font-weight: 700;
|
|
198
|
+
padding: 5px 12px;
|
|
199
|
+
border-radius: 6px;
|
|
162
200
|
text-transform: uppercase;
|
|
163
|
-
letter-spacing: 0.05em;
|
|
164
|
-
margin-bottom: 6px;
|
|
165
201
|
}
|
|
166
202
|
|
|
167
|
-
.
|
|
203
|
+
.verdict-clean {
|
|
204
|
+
color: var(--face-ok);
|
|
205
|
+
background: rgba(16, 185, 129, 0.15);
|
|
206
|
+
border: 1px solid rgba(16, 185, 129, 0.4);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.verdict-failed {
|
|
210
|
+
color: var(--face-danger);
|
|
211
|
+
background: rgba(239, 68, 68, 0.15);
|
|
212
|
+
border: 1px solid rgba(239, 68, 68, 0.4);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.verdict-pending {
|
|
216
|
+
color: var(--text-secondary, var(--face-muted));
|
|
217
|
+
background: rgba(148, 163, 184, 0.1);
|
|
218
|
+
border: 1px solid var(--border, var(--face-line));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* Tier & Execution Bar */
|
|
222
|
+
.controls-deck {
|
|
168
223
|
display: flex;
|
|
224
|
+
align-items: center;
|
|
225
|
+
justify-content: space-between;
|
|
169
226
|
flex-wrap: wrap;
|
|
170
|
-
gap:
|
|
227
|
+
gap: 10px;
|
|
228
|
+
margin-bottom: 16px;
|
|
229
|
+
background: rgba(30, 41, 59, 0.5);
|
|
230
|
+
border: 1px solid var(--border, var(--face-line));
|
|
231
|
+
border-radius: 6px;
|
|
232
|
+
padding: 8px 12px;
|
|
171
233
|
}
|
|
172
234
|
|
|
173
|
-
.
|
|
235
|
+
.tier-toggles {
|
|
174
236
|
display: flex;
|
|
175
237
|
align-items: center;
|
|
176
238
|
gap: 6px;
|
|
177
|
-
|
|
178
|
-
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.btn-tier {
|
|
242
|
+
min-height: 44px;
|
|
243
|
+
min-width: 44px;
|
|
244
|
+
padding: 8px 14px;
|
|
245
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
179
246
|
font-size: 11px;
|
|
180
|
-
font-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
247
|
+
font-weight: 700;
|
|
248
|
+
color: var(--text-secondary, var(--face-muted));
|
|
249
|
+
background: transparent;
|
|
250
|
+
border: 1px solid var(--border, var(--face-line));
|
|
251
|
+
border-radius: 5px;
|
|
252
|
+
cursor: pointer;
|
|
253
|
+
transition: all 0.2s ease;
|
|
184
254
|
}
|
|
185
255
|
|
|
186
|
-
.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
border-radius: 50%;
|
|
190
|
-
background: #06b6d4;
|
|
191
|
-
box-shadow: 0 0 6px rgba(6, 182, 212, 0.8);
|
|
256
|
+
.btn-tier:hover {
|
|
257
|
+
color: var(--text-primary, var(--face-text));
|
|
258
|
+
border-color: var(--card-accent, var(--face-accent));
|
|
192
259
|
}
|
|
193
260
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
261
|
+
.btn-tier[data-active="true"] {
|
|
262
|
+
color: var(--face-dark);
|
|
263
|
+
background: var(--card-accent, var(--face-accent));
|
|
264
|
+
border-color: var(--card-accent, var(--face-accent));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.action-group {
|
|
268
|
+
display: flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
gap: 8px;
|
|
200
271
|
}
|
|
201
272
|
|
|
202
|
-
.btn-
|
|
273
|
+
.btn-run {
|
|
203
274
|
min-height: 44px;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
border-radius: 8px;
|
|
208
|
-
color: #ecfeff;
|
|
209
|
-
font-family: 'Space Grotesk', sans-serif;
|
|
210
|
-
font-size: 11px;
|
|
275
|
+
padding: 8px 16px;
|
|
276
|
+
font-family: var(--font-sans, sans-serif);
|
|
277
|
+
font-size: 12px;
|
|
211
278
|
font-weight: 700;
|
|
212
|
-
|
|
279
|
+
color: var(--face-dark);
|
|
280
|
+
background: var(--face-brand);
|
|
281
|
+
border: none;
|
|
282
|
+
border-radius: 5px;
|
|
213
283
|
cursor: pointer;
|
|
214
|
-
touch-action: manipulation;
|
|
215
284
|
display: flex;
|
|
216
285
|
align-items: center;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
padding: 6px;
|
|
220
|
-
transition: all 0.15s ease;
|
|
286
|
+
gap: 6px;
|
|
287
|
+
transition: background 0.2s ease;
|
|
221
288
|
}
|
|
222
289
|
|
|
223
|
-
.btn-
|
|
224
|
-
background:
|
|
225
|
-
border-color: #06b6d4;
|
|
226
|
-
color: #ffffff;
|
|
290
|
+
.btn-run:hover {
|
|
291
|
+
background: var(--face-brand-hover);
|
|
227
292
|
}
|
|
228
293
|
|
|
229
|
-
.btn-
|
|
230
|
-
|
|
294
|
+
.btn-run:disabled {
|
|
295
|
+
opacity: 0.6;
|
|
296
|
+
cursor: not-allowed;
|
|
231
297
|
}
|
|
232
298
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
299
|
+
/* Gate Matrix Grid */
|
|
300
|
+
.section-title {
|
|
301
|
+
font-size: 12px;
|
|
302
|
+
font-weight: 700;
|
|
303
|
+
letter-spacing: 0.05em;
|
|
304
|
+
text-transform: uppercase;
|
|
305
|
+
color: var(--text-secondary, var(--face-muted));
|
|
306
|
+
margin: 0 0 10px 0;
|
|
237
307
|
}
|
|
238
308
|
|
|
239
|
-
.
|
|
240
|
-
|
|
241
|
-
|
|
309
|
+
.gate-grid {
|
|
310
|
+
display: grid;
|
|
311
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
312
|
+
gap: 10px;
|
|
313
|
+
margin-bottom: 18px;
|
|
242
314
|
}
|
|
243
315
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
border:
|
|
248
|
-
|
|
249
|
-
|
|
316
|
+
.gate-card {
|
|
317
|
+
background: rgba(30, 41, 59, 0.4);
|
|
318
|
+
border: 1px solid var(--border, var(--face-line));
|
|
319
|
+
border-radius: 6px;
|
|
320
|
+
padding: 10px;
|
|
321
|
+
display: flex;
|
|
322
|
+
flex-direction: column;
|
|
323
|
+
gap: 6px;
|
|
250
324
|
}
|
|
251
325
|
|
|
252
|
-
.
|
|
326
|
+
.gate-head {
|
|
253
327
|
display: flex;
|
|
254
|
-
justify-content: space-between;
|
|
255
328
|
align-items: center;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
329
|
+
justify-content: space-between;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.gate-name {
|
|
333
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
334
|
+
font-size: 11px;
|
|
335
|
+
font-weight: 700;
|
|
336
|
+
color: var(--text-primary, var(--face-text));
|
|
259
337
|
}
|
|
260
338
|
|
|
261
|
-
.
|
|
262
|
-
font-family: 'JetBrains Mono', monospace;
|
|
339
|
+
.gate-badge {
|
|
263
340
|
font-size: 9px;
|
|
264
|
-
|
|
341
|
+
font-weight: 700;
|
|
342
|
+
padding: 2px 6px;
|
|
343
|
+
border-radius: 4px;
|
|
265
344
|
text-transform: uppercase;
|
|
266
|
-
letter-spacing: 0.05em;
|
|
267
345
|
}
|
|
268
346
|
|
|
269
|
-
.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
347
|
+
.badge-passed {
|
|
348
|
+
color: var(--face-ok);
|
|
349
|
+
background: rgba(16, 185, 129, 0.15);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.badge-failed {
|
|
353
|
+
color: var(--face-danger);
|
|
354
|
+
background: rgba(239, 68, 68, 0.15);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.badge-skipped {
|
|
358
|
+
color: var(--text-secondary, var(--face-muted));
|
|
359
|
+
background: rgba(148, 163, 184, 0.1);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.gate-meta {
|
|
363
|
+
display: flex;
|
|
364
|
+
justify-content: space-between;
|
|
274
365
|
font-size: 10px;
|
|
366
|
+
color: var(--text-secondary, var(--face-muted));
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* Violation Browser */
|
|
370
|
+
.filter-tabs {
|
|
371
|
+
display: flex;
|
|
372
|
+
align-items: center;
|
|
373
|
+
gap: 8px;
|
|
374
|
+
margin-bottom: 10px;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.filter-btn {
|
|
378
|
+
min-height: 44px;
|
|
379
|
+
padding: 6px 12px;
|
|
380
|
+
font-size: 11px;
|
|
381
|
+
font-weight: 600;
|
|
382
|
+
color: var(--text-secondary, var(--face-muted));
|
|
383
|
+
background: transparent;
|
|
384
|
+
border: 1px solid var(--border, var(--face-line));
|
|
385
|
+
border-radius: 5px;
|
|
275
386
|
cursor: pointer;
|
|
276
|
-
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.filter-btn[data-active="true"] {
|
|
390
|
+
color: var(--text-primary, var(--face-text));
|
|
391
|
+
background: rgba(56, 189, 248, 0.15);
|
|
392
|
+
border-color: var(--card-accent, var(--face-accent));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.violations-box {
|
|
396
|
+
border: 1px solid var(--border, var(--face-line));
|
|
397
|
+
border-radius: 6px;
|
|
398
|
+
background: rgba(15, 23, 42, 0.6);
|
|
399
|
+
max-height: 240px;
|
|
400
|
+
overflow-y: auto;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.violation-row {
|
|
404
|
+
padding: 8px 12px;
|
|
405
|
+
border-bottom: 1px solid rgba(51, 65, 85, 0.5);
|
|
406
|
+
display: flex;
|
|
407
|
+
flex-direction: column;
|
|
408
|
+
gap: 4px;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.violation-row:last-child {
|
|
412
|
+
border-bottom: none;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.violation-header {
|
|
416
|
+
display: flex;
|
|
417
|
+
align-items: center;
|
|
418
|
+
gap: 8px;
|
|
419
|
+
font-size: 11px;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.severity-tag {
|
|
423
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
424
|
+
font-size: 9px;
|
|
425
|
+
font-weight: 700;
|
|
426
|
+
padding: 2px 6px;
|
|
277
427
|
border-radius: 4px;
|
|
428
|
+
text-transform: uppercase;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.severity-error {
|
|
432
|
+
color: var(--face-danger);
|
|
433
|
+
background: rgba(239, 68, 68, 0.18);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.severity-warning {
|
|
437
|
+
color: var(--face-warn);
|
|
438
|
+
background: rgba(245, 158, 11, 0.18);
|
|
278
439
|
}
|
|
279
440
|
|
|
280
|
-
.
|
|
281
|
-
|
|
441
|
+
.violation-loc {
|
|
442
|
+
font-family: var(--font-mono, 'JetBrains Mono', monospace);
|
|
443
|
+
color: var(--card-accent, var(--face-accent));
|
|
282
444
|
}
|
|
283
445
|
|
|
284
|
-
.
|
|
285
|
-
font-family: 'JetBrains Mono', monospace;
|
|
446
|
+
.violation-msg {
|
|
286
447
|
font-size: 11px;
|
|
448
|
+
color: var(--text-primary, var(--face-text));
|
|
287
449
|
line-height: 1.4;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.empty-violations {
|
|
453
|
+
padding: 24px;
|
|
454
|
+
text-align: center;
|
|
455
|
+
font-size: 12px;
|
|
456
|
+
color: var(--face-ok);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Footer Telemetry */
|
|
460
|
+
.footer-bar {
|
|
461
|
+
display: flex;
|
|
462
|
+
justify-content: space-between;
|
|
463
|
+
align-items: center;
|
|
464
|
+
padding-top: 12px;
|
|
465
|
+
margin-top: 14px;
|
|
466
|
+
border-top: 1px solid var(--border, var(--face-line));
|
|
467
|
+
font-size: 10px;
|
|
468
|
+
color: var(--text-secondary, var(--face-muted));
|
|
294
469
|
}
|
|
295
470
|
</style>
|
|
296
471
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
<
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
<span class="metric-label">Execution Tier</span>
|
|
305
|
-
<span class="metric-value" id="stat-tier">${this.telemetry.tier}</span>
|
|
472
|
+
<div class="header">
|
|
473
|
+
<div class="brand-group">
|
|
474
|
+
<div class="wordmark-badge">[NIT//PICKER]</div>
|
|
475
|
+
<div class="title-meta">
|
|
476
|
+
<h3 class="plugin-title">Code Quality Gates</h3>
|
|
477
|
+
<p class="plugin-subtitle">Fail-closed deterministic repository verification</p>
|
|
478
|
+
</div>
|
|
306
479
|
</div>
|
|
307
|
-
<div class="
|
|
308
|
-
|
|
309
|
-
<span class="metric-value" id="stat-status">${this.telemetry.status}</span>
|
|
480
|
+
<div class="verdict-chip ${rep ? (isClean ? 'verdict-clean' : 'verdict-failed') : 'verdict-pending'}">
|
|
481
|
+
${this.executing ? 'Checking...' : rep ? (isClean ? 'Clean · Pass' : `${errorCount} Errors · Failed`) : 'Pending Report'}
|
|
310
482
|
</div>
|
|
311
483
|
</div>
|
|
312
484
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
<
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
<
|
|
485
|
+
<div class="controls-deck">
|
|
486
|
+
<div class="tier-toggles">
|
|
487
|
+
<button class="btn-tier" data-active="${tierName === 'fast'}" type="button" id="tier-fast">Fast</button>
|
|
488
|
+
<button class="btn-tier" data-active="${tierName === 'full'}" type="button" id="tier-full">Full</button>
|
|
489
|
+
<button class="btn-tier" data-active="${tierName === 'remote'}" type="button" id="tier-remote">Remote</button>
|
|
490
|
+
</div>
|
|
491
|
+
<div class="action-group">
|
|
492
|
+
<button class="btn-run" type="button" id="btn-run" ${this.executing ? 'disabled' : ''}>
|
|
493
|
+
${this.executing ? 'Verifying...' : `Run ${tierName.toUpperCase()} Gate`}
|
|
494
|
+
</button>
|
|
321
495
|
</div>
|
|
322
496
|
</div>
|
|
323
497
|
|
|
324
|
-
|
|
325
|
-
<div class="
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
498
|
+
<div class="section-title">Configured Gate Matrix</div>
|
|
499
|
+
<div class="gate-grid">
|
|
500
|
+
${checks.length > 0 ? checks.map(c => `
|
|
501
|
+
<div class="gate-card">
|
|
502
|
+
<div class="gate-head">
|
|
503
|
+
<span class="gate-name">${escapeHtml(c.name || c.id)}</span>
|
|
504
|
+
<span class="gate-badge badge-${escapeHtml(c.status || 'passed')}">${escapeHtml(c.status || 'passed')}</span>
|
|
505
|
+
</div>
|
|
506
|
+
<div class="gate-meta">
|
|
507
|
+
<span>Exit ${c.exit_code !== undefined ? c.exit_code : 0}</span>
|
|
508
|
+
<span>${c.duration_ms ? `${c.duration_ms}ms` : DASH}</span>
|
|
509
|
+
</div>
|
|
510
|
+
</div>
|
|
511
|
+
`).join('') : `
|
|
512
|
+
<div class="gate-card">
|
|
513
|
+
<div class="gate-head">
|
|
514
|
+
<span class="gate-name">Syntax & Types</span>
|
|
515
|
+
<span class="gate-badge badge-skipped">Pending</span>
|
|
516
|
+
</div>
|
|
517
|
+
<div class="gate-meta"><span>Exit ${DASH}</span><span>${DASH}</span></div>
|
|
518
|
+
</div>
|
|
519
|
+
<div class="gate-card">
|
|
520
|
+
<div class="gate-head">
|
|
521
|
+
<span class="gate-name">Unit Tests</span>
|
|
522
|
+
<span class="gate-badge badge-skipped">Pending</span>
|
|
523
|
+
</div>
|
|
524
|
+
<div class="gate-meta"><span>Exit ${DASH}</span><span>${DASH}</span></div>
|
|
525
|
+
</div>
|
|
526
|
+
<div class="gate-card">
|
|
527
|
+
<div class="gate-head">
|
|
528
|
+
<span class="gate-name">Lint & Imports</span>
|
|
529
|
+
<span class="gate-badge badge-skipped">Pending</span>
|
|
530
|
+
</div>
|
|
531
|
+
<div class="gate-meta"><span>Exit ${DASH}</span><span>${DASH}</span></div>
|
|
532
|
+
</div>
|
|
533
|
+
`}
|
|
332
534
|
</div>
|
|
333
535
|
|
|
334
|
-
|
|
335
|
-
<div class="
|
|
336
|
-
<
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
536
|
+
<div class="section-title">Inspection Findings (${filteredFindings.length})</div>
|
|
537
|
+
<div class="filter-tabs">
|
|
538
|
+
<button class="filter-btn" data-active="${this.activeFilter === 'all'}" type="button" id="filter-all">
|
|
539
|
+
All (${allFindings.length})
|
|
540
|
+
</button>
|
|
541
|
+
<button class="filter-btn" data-active="${this.activeFilter === 'errors'}" type="button" id="filter-errors">
|
|
542
|
+
Errors (${errorCount})
|
|
543
|
+
</button>
|
|
544
|
+
<button class="filter-btn" data-active="${this.activeFilter === 'warnings'}" type="button" id="filter-warnings">
|
|
545
|
+
Warnings (${warnCount})
|
|
546
|
+
</button>
|
|
547
|
+
</div>
|
|
548
|
+
|
|
549
|
+
<div class="violations-box">
|
|
550
|
+
${filteredFindings.length > 0 ? filteredFindings.map(f => `
|
|
551
|
+
<div class="violation-row">
|
|
552
|
+
<div class="violation-header">
|
|
553
|
+
<span class="severity-tag severity-${escapeHtml(f.severity || 'error')}">${escapeHtml(f.severity || 'error')}</span>
|
|
554
|
+
<span class="violation-loc">${escapeHtml(f.file || 'unknown')}${f.line ? `:${f.line}` : ''}</span>
|
|
555
|
+
${f.rule_id ? `<span class="plugin-subtitle">[${escapeHtml(f.rule_id)}]</span>` : ''}
|
|
556
|
+
</div>
|
|
557
|
+
<div class="violation-msg">${escapeHtml(f.message || 'Verification failure detected')}</div>
|
|
558
|
+
</div>
|
|
559
|
+
`).join('') : `
|
|
560
|
+
<div class="empty-violations">
|
|
561
|
+
${rep ? 'Zero violations detected. Repository passes clean.' : 'No active gate report found. Click Run Gate above.'}
|
|
562
|
+
</div>
|
|
563
|
+
`}
|
|
564
|
+
</div>
|
|
565
|
+
|
|
566
|
+
<div class="footer-bar">
|
|
567
|
+
<span>Latest Run: ${timestamp}</span>
|
|
568
|
+
<span>Tier: ${tierName.toUpperCase()}</span>
|
|
341
569
|
</div>
|
|
342
570
|
`;
|
|
343
571
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
if (cmd) this.execute(cmd, []);
|
|
349
|
-
});
|
|
350
|
-
});
|
|
572
|
+
// Event listeners
|
|
573
|
+
root.querySelector('#tier-fast')?.addEventListener('click', () => { this.selectedTier = 'fast'; this.render(); });
|
|
574
|
+
root.querySelector('#tier-full')?.addEventListener('click', () => { this.selectedTier = 'full'; this.render(); });
|
|
575
|
+
root.querySelector('#tier-remote')?.addEventListener('click', () => { this.selectedTier = 'remote'; this.render(); });
|
|
351
576
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
navigator.clipboard?.writeText(out.textContent);
|
|
358
|
-
copyBtn.textContent = 'Copied!';
|
|
359
|
-
setTimeout(() => { copyBtn.textContent = 'Copy'; }, 1500);
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
}
|
|
577
|
+
root.querySelector('#btn-run')?.addEventListener('click', () => this.runTier(this.selectedTier));
|
|
578
|
+
|
|
579
|
+
root.querySelector('#filter-all')?.addEventListener('click', () => this.setFilter('all'));
|
|
580
|
+
root.querySelector('#filter-errors')?.addEventListener('click', () => this.setFilter('errors'));
|
|
581
|
+
root.querySelector('#filter-warnings')?.addEventListener('click', () => this.setFilter('warnings'));
|
|
363
582
|
}
|
|
364
583
|
}
|
|
365
584
|
|