pi-mega-compact 0.20.26 → 0.20.28
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/dist/config/vector-cortex-vc9a.js +29 -0
- package/dist/config/vector-cortex-vc9b.js +29 -0
- package/dist/config/vector-cortex-vc9c.js +34 -0
- package/dist/config/vector-cortex.js +4 -0
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry-ext.js +20 -0
- package/dist/extensions/dashboard-server/api-contracts/setup-cortex.js +13 -0
- package/dist/extensions/dashboard-server/route-dispatch.js +7 -1
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +3 -0
- package/dist/extensions/dashboard-server/routes-setup-cortex-actions.js +116 -0
- package/dist/extensions/dashboard-server/routes-setup-cortex.js +143 -0
- package/dist/extensions/dashboard-server/routes.js +2 -0
- package/dist/extensions/dashboard-server/setup-cortex-actions.js +213 -0
- package/dist/extensions/dashboard-server/setup-cortex-blockers.js +70 -0
- package/dist/src/config/vector-cortex-vc9a.js +29 -0
- package/dist/src/config/vector-cortex-vc9b.js +29 -0
- package/dist/src/config/vector-cortex-vc9c.js +34 -0
- package/dist/src/config/vector-cortex.js +4 -0
- package/dist/src/config.js +1 -1
- package/extensions/dashboard-client/dist/assets/{AreaChart-DRErPez1.js → AreaChart-DIKsPqLG.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-DRErPez1.js.map → AreaChart-DIKsPqLG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-Cwxel3M7.js → BarChart-DeqN74Hn.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-Cwxel3M7.js.map → BarChart-DeqN74Hn.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-D4j3vwFu.js → CacheTab-x1YU4tYc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-D4j3vwFu.js.map → CacheTab-x1YU4tYc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-BA7t_fsH.js → EventsTab-6BuEbd8Y.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-BA7t_fsH.js.map → EventsTab-6BuEbd8Y.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-Ci9gtYDP.js → HealthTab-B71Ft1ac.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-Ci9gtYDP.js.map → HealthTab-B71Ft1ac.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-BeqWn-xu.js → MaintenanceTab-dysyJtHk.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-BeqWn-xu.js.map → MaintenanceTab-dysyJtHk.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BreZegCV.js → MemoryMapTab-B3dKRb_4.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BreZegCV.js.map → MemoryMapTab-B3dKRb_4.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-DLbgfJT2.js → MetricsTab-COn4GoUK.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-DLbgfJT2.js.map → MetricsTab-COn4GoUK.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BtcXdrnC.js → OverviewTab-Cd9qAEB3.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BtcXdrnC.js.map → OverviewTab-Cd9qAEB3.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-DpDLEzV9.js → ReposTab-DpiP1-Vv.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-DpDLEzV9.js.map → ReposTab-DpiP1-Vv.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-CMe5jSrZ.js → SessionsTab-BwRUeGZM.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-CMe5jSrZ.js.map → SessionsTab-BwRUeGZM.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-CJFDD2_v.js +3 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CJFDD2_v.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BFPJUQzs.js → TimeSavedCard-_XsdjQ7Z.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-BFPJUQzs.js.map → TimeSavedCard-_XsdjQ7Z.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-Ujt29pKI.js → TurnsTab-CWPscPLL.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-Ujt29pKI.js.map → TurnsTab-CWPscPLL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VcStatusBadge-Cx56rAIM.js +2 -0
- package/extensions/dashboard-client/dist/assets/VcStatusBadge-Cx56rAIM.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-B5ElUM7S.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-B5ElUM7S.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-BiKXVwGT.js → WikiTab-uZ5Mq3XG.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-BiKXVwGT.js.map → WikiTab-uZ5Mq3XG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-DJwGcw0u.js → button-Kc18bYFz.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-DJwGcw0u.js.map → button-Kc18bYFz.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-CgjBf5LZ.js → card-COJZoG08.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-CgjBf5LZ.js.map → card-COJZoG08.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-CTQIl2qs.js → generateCategoricalChart-ChEYo017.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-CTQIl2qs.js.map → generateCategoricalChart-ChEYo017.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-Bu8CZUMX.js → index-CB7Rn5FP.js} +14 -14
- package/extensions/dashboard-client/dist/assets/index-CB7Rn5FP.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-DbuGwYD7.css +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-uUiS1Raq.js → switch-BFhl_tNh.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-uUiS1Raq.js.map → switch-BFhl_tNh.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-Dv3OEscH.js → toggle-DJ68kATc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-Dv3OEscH.js.map → toggle-DJ68kATc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-n6ymAic3.js → useSSE-CXWh42xX.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-n6ymAic3.js.map → useSSE-CXWh42xX.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/src/api/setup-cortex.ts +62 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/CortexActionsCard.tsx +221 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/CortexBlockersCard.tsx +74 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/CortexEncoderCard.tsx +113 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/CortexSetup.tsx +53 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/CortexSetupStyles.ts +98 -0
- package/extensions/dashboard-client/src/tabs/SetupTab.tsx +22 -6
- package/extensions/dashboard-client/src/tabs/useSetupCortexPoll.ts +64 -0
- package/extensions/dashboard-client/src/types/setup-cortex.ts +118 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry-ext.ts +44 -0
- package/extensions/dashboard-server/api-contracts/setup-cortex.ts +123 -0
- package/extensions/dashboard-server/route-dispatch.ts +6 -0
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +18 -0
- package/extensions/dashboard-server/routes-setup-cortex-actions.ts +133 -0
- package/extensions/dashboard-server/routes-setup-cortex.ts +167 -0
- package/extensions/dashboard-server/routes.ts +5 -0
- package/extensions/dashboard-server/setup-cortex-actions.ts +242 -0
- package/extensions/dashboard-server/setup-cortex-blockers.ts +98 -0
- package/package.json +1 -1
- package/src/config/vector-cortex-vc9a.ts +31 -0
- package/src/config/vector-cortex-vc9b.ts +31 -0
- package/src/config/vector-cortex-vc9c.ts +36 -0
- package/src/config/vector-cortex.ts +5 -0
- package/src/config.ts +3 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-C3OY8mc7.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-C3OY8mc7.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-CfxZW91A.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-CfxZW91A.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-Bu8CZUMX.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-Difwoltx.css +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-client/src/api/setup-cortex.ts — Setup Cortex API client.
|
|
3
|
+
*
|
|
4
|
+
* Fetches the VC9A status + drives the VC9B actions against the localhost
|
|
5
|
+
* dashboard server. PREVENT-PI-004: relative loopback paths only — the client
|
|
6
|
+
* is served by the local dashboard server, so no external network call.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
SetupCortexStatusResponse,
|
|
11
|
+
SetupCortexActionRequest,
|
|
12
|
+
SetupCortexActionResult,
|
|
13
|
+
SetupCortexActionErrorBody,
|
|
14
|
+
SetupCortexActionLogResponse,
|
|
15
|
+
} from "../types/setup-cortex";
|
|
16
|
+
|
|
17
|
+
/** Reader-only status aggregate (GET /api/setup-cortex-status). */
|
|
18
|
+
export async function fetchSetupCortexStatus(): Promise<SetupCortexStatusResponse> {
|
|
19
|
+
const r = await fetch("/api/setup-cortex-status");
|
|
20
|
+
if (!r.ok) throw new Error(`setup-cortex status: ${r.status}`);
|
|
21
|
+
return r.json() as Promise<SetupCortexStatusResponse>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Drive one Setup Cortex action (POST /api/setup-cortex-action).
|
|
26
|
+
*
|
|
27
|
+
* Returns a discriminated union so the UI can render the blocked /
|
|
28
|
+
* confirmation-required / disabled states honestly instead of swallowing the
|
|
29
|
+
* server's typed error body.
|
|
30
|
+
*/
|
|
31
|
+
export type SetupCortexActionOutcome =
|
|
32
|
+
| { ok: true; result: SetupCortexActionResult }
|
|
33
|
+
| { ok: false; status: number; error: SetupCortexActionErrorBody };
|
|
34
|
+
|
|
35
|
+
export async function postSetupCortexAction(
|
|
36
|
+
body: SetupCortexActionRequest,
|
|
37
|
+
): Promise<SetupCortexActionOutcome> {
|
|
38
|
+
const r = await fetch("/api/setup-cortex-action", {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "Content-Type": "application/json" },
|
|
41
|
+
body: JSON.stringify(body),
|
|
42
|
+
});
|
|
43
|
+
if (r.ok) {
|
|
44
|
+
return { ok: true, result: (await r.json()) as SetupCortexActionResult };
|
|
45
|
+
}
|
|
46
|
+
let error: SetupCortexActionErrorBody;
|
|
47
|
+
try {
|
|
48
|
+
error = (await r.json()) as SetupCortexActionErrorBody;
|
|
49
|
+
} catch {
|
|
50
|
+
error = { error: "disabled" };
|
|
51
|
+
}
|
|
52
|
+
return { ok: false, status: r.status, error };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Bounded, redacted log tail (GET /api/setup-cortex-action-log?name=...). */
|
|
56
|
+
export async function fetchSetupCortexActionLog(
|
|
57
|
+
name: string,
|
|
58
|
+
): Promise<SetupCortexActionLogResponse> {
|
|
59
|
+
const r = await fetch(`/api/setup-cortex-action-log?name=${encodeURIComponent(name)}`);
|
|
60
|
+
if (!r.ok) throw new Error(`setup-cortex action-log: ${r.status}`);
|
|
61
|
+
return r.json() as Promise<SetupCortexActionLogResponse>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SetupTab/CortexActionsCard.tsx — confirmation-gated Setup Cortex actions.
|
|
3
|
+
*
|
|
4
|
+
* fetch-model / bench / verify-asset. Uses the MaintenanceTab ActionDef +
|
|
5
|
+
* window.confirm pattern; the POST body ALWAYS carries confirm:true (the
|
|
6
|
+
* server hard-requires it). A 423 action_blocked_by_open_item surfaces the
|
|
7
|
+
* gating blocker ids to the parent (which highlights the rows), a 400
|
|
8
|
+
* confirmation_required and a 404 disabled are rendered honestly, and on a
|
|
9
|
+
* successful run the returned logName is shown with a bounded log tail fetch.
|
|
10
|
+
*/
|
|
11
|
+
import type React from "react";
|
|
12
|
+
import { useState, useCallback } from "react";
|
|
13
|
+
import type {
|
|
14
|
+
SetupCortexActionKind,
|
|
15
|
+
SetupCortexStatusResponse,
|
|
16
|
+
} from "../../types/setup-cortex";
|
|
17
|
+
import {
|
|
18
|
+
postSetupCortexAction,
|
|
19
|
+
fetchSetupCortexActionLog,
|
|
20
|
+
} from "../../api/setup-cortex";
|
|
21
|
+
import { styles } from "./CortexSetupStyles";
|
|
22
|
+
|
|
23
|
+
interface ActionDef {
|
|
24
|
+
key: SetupCortexActionKind;
|
|
25
|
+
label: string;
|
|
26
|
+
desc: string;
|
|
27
|
+
dangerous: boolean;
|
|
28
|
+
confirm: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const ACTIONS: ActionDef[] = [
|
|
32
|
+
{
|
|
33
|
+
key: "fetch-model",
|
|
34
|
+
label: "Fetch Model",
|
|
35
|
+
desc: "Fetch the qualified encoder model asset",
|
|
36
|
+
dangerous: true,
|
|
37
|
+
confirm:
|
|
38
|
+
"Fetch the encoder model asset onto this host? (Gated by any open hard gate.)",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "bench",
|
|
42
|
+
label: "Bench Encoder",
|
|
43
|
+
desc: "Benchmark the encoder runtime on this host",
|
|
44
|
+
dangerous: true,
|
|
45
|
+
confirm:
|
|
46
|
+
"Run an encoder benchmark on this host? (Gated by any open hard gate.)",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
key: "verify-asset",
|
|
50
|
+
label: "Verify Asset",
|
|
51
|
+
desc: "Re-verify the committed encoder asset",
|
|
52
|
+
dangerous: false,
|
|
53
|
+
confirm: "Re-verify the committed encoder asset?",
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
interface ActionResultDisplay {
|
|
58
|
+
action: string;
|
|
59
|
+
logName: string;
|
|
60
|
+
tail: string | null;
|
|
61
|
+
complete: boolean | null;
|
|
62
|
+
message: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function CortexActionsCard({
|
|
66
|
+
data,
|
|
67
|
+
onBlocked,
|
|
68
|
+
onAction,
|
|
69
|
+
}: {
|
|
70
|
+
data: SetupCortexStatusResponse | null;
|
|
71
|
+
onBlocked: (blockerIds: string[]) => void;
|
|
72
|
+
onAction: () => void;
|
|
73
|
+
}): React.ReactElement {
|
|
74
|
+
const [running, setRunning] = useState<SetupCortexActionKind | null>(null);
|
|
75
|
+
const [result, setResult] = useState<ActionResultDisplay | null>(null);
|
|
76
|
+
const [actionError, setActionError] = useState<string | null>(null);
|
|
77
|
+
const [disabled, setDisabled] = useState(false);
|
|
78
|
+
|
|
79
|
+
const runAction = useCallback(
|
|
80
|
+
async (def: ActionDef) => {
|
|
81
|
+
setRunning(def.key);
|
|
82
|
+
setActionError(null);
|
|
83
|
+
setResult(null);
|
|
84
|
+
setDisabled(false);
|
|
85
|
+
onBlocked([]);
|
|
86
|
+
try {
|
|
87
|
+
const outcome = await postSetupCortexAction({
|
|
88
|
+
action: def.key,
|
|
89
|
+
confirm: true,
|
|
90
|
+
});
|
|
91
|
+
if (outcome.ok) {
|
|
92
|
+
const r = outcome.result;
|
|
93
|
+
let tail: string | null = null;
|
|
94
|
+
let complete: boolean | null = null;
|
|
95
|
+
try {
|
|
96
|
+
const log = await fetchSetupCortexActionLog(r.logName);
|
|
97
|
+
tail = log.tail;
|
|
98
|
+
complete = log.complete;
|
|
99
|
+
} catch {
|
|
100
|
+
/* log tail is best-effort */
|
|
101
|
+
}
|
|
102
|
+
setResult({
|
|
103
|
+
action: r.action,
|
|
104
|
+
logName: r.logName,
|
|
105
|
+
tail,
|
|
106
|
+
complete,
|
|
107
|
+
message: r.ok
|
|
108
|
+
? `${r.action} completed (spawned: ${r.spawned})`
|
|
109
|
+
: `${r.action} did not complete cleanly`,
|
|
110
|
+
});
|
|
111
|
+
onAction();
|
|
112
|
+
} else if (outcome.error.error === "action_blocked_by_open_item") {
|
|
113
|
+
onBlocked(outcome.error.blockers);
|
|
114
|
+
setActionError(
|
|
115
|
+
"The action is blocked by an open hard-gate item and was not run.",
|
|
116
|
+
);
|
|
117
|
+
} else if (outcome.error.error === "confirmation_required") {
|
|
118
|
+
setActionError(
|
|
119
|
+
"The server rejected the action: explicit confirmation is required.",
|
|
120
|
+
);
|
|
121
|
+
} else {
|
|
122
|
+
setDisabled(true);
|
|
123
|
+
setActionError(
|
|
124
|
+
outcome.status === 404
|
|
125
|
+
? "Setup Cortex actions are disabled (off)."
|
|
126
|
+
: `Action failed (${outcome.status}).`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
setActionError(e instanceof Error ? e.message : String(e));
|
|
131
|
+
} finally {
|
|
132
|
+
setRunning(null);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
[onBlocked, onAction],
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
const handleClick = (def: ActionDef) => {
|
|
139
|
+
if (!window.confirm(def.confirm)) return;
|
|
140
|
+
void runAction(def);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<div style={styles.section}>
|
|
145
|
+
<h3 style={styles.sectionTitle}>Cortex Actions</h3>
|
|
146
|
+
|
|
147
|
+
{ACTIONS.map((def) => {
|
|
148
|
+
const isRunning = running === def.key;
|
|
149
|
+
return (
|
|
150
|
+
<div
|
|
151
|
+
key={def.key}
|
|
152
|
+
style={{
|
|
153
|
+
display: "flex",
|
|
154
|
+
alignItems: "center",
|
|
155
|
+
justifyContent: "space-between",
|
|
156
|
+
gap: "0.5rem",
|
|
157
|
+
padding: "0.5rem 0",
|
|
158
|
+
borderBottom: "1px solid #2a2a4e",
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<div>
|
|
162
|
+
<div style={{ fontWeight: 600 }}>{def.label}</div>
|
|
163
|
+
<div style={{ fontSize: "0.8rem", color: "#a0a0c0" }}>
|
|
164
|
+
{def.desc}
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
<button
|
|
168
|
+
style={def.dangerous ? styles.buttonDanger : styles.button}
|
|
169
|
+
disabled={running !== null}
|
|
170
|
+
onClick={() => handleClick(def)}
|
|
171
|
+
>
|
|
172
|
+
{isRunning ? "Running…" : "Run"}
|
|
173
|
+
</button>
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
})}
|
|
177
|
+
|
|
178
|
+
{disabled && (
|
|
179
|
+
<div style={styles.blocked}>
|
|
180
|
+
Setup Cortex actions are disabled. Enable MEGACOMPACT_VC9B to run
|
|
181
|
+
them.
|
|
182
|
+
</div>
|
|
183
|
+
)}
|
|
184
|
+
{actionError && !disabled && (
|
|
185
|
+
<p style={{ color: "#f44336", fontSize: "0.85rem", marginTop: "0.5rem" }}>
|
|
186
|
+
{actionError}
|
|
187
|
+
</p>
|
|
188
|
+
)}
|
|
189
|
+
{result && (
|
|
190
|
+
<div style={styles.warning} data-testid="cortex-action-result">
|
|
191
|
+
<strong>Result ({result.action}):</strong> {result.message}
|
|
192
|
+
{result.logName && (
|
|
193
|
+
<span style={{ ...styles.mono, marginLeft: "0.5rem" }}>
|
|
194
|
+
log: {result.logName}
|
|
195
|
+
</span>
|
|
196
|
+
)}
|
|
197
|
+
{result.tail !== null && (
|
|
198
|
+
<pre
|
|
199
|
+
style={{
|
|
200
|
+
whiteSpace: "pre-wrap",
|
|
201
|
+
wordBreak: "break-word",
|
|
202
|
+
fontSize: "0.75rem",
|
|
203
|
+
maxHeight: "12rem",
|
|
204
|
+
overflow: "auto",
|
|
205
|
+
marginTop: "0.5rem",
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
{result.tail}
|
|
209
|
+
{result.complete === false && "\n… (truncated)"}
|
|
210
|
+
</pre>
|
|
211
|
+
)}
|
|
212
|
+
</div>
|
|
213
|
+
)}
|
|
214
|
+
{!data?.enabled && !disabled && (
|
|
215
|
+
<p style={{ color: "#a0a0c0", fontSize: "0.8rem", marginTop: "0.5rem" }}>
|
|
216
|
+
Cortex status unavailable — actions may not be schedulable.
|
|
217
|
+
</p>
|
|
218
|
+
)}
|
|
219
|
+
</div>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SetupTab/CortexBlockersCard.tsx — open hard-gate blockers card (VC9C).
|
|
3
|
+
*
|
|
4
|
+
* Renders the STATUS payload's `blockers` rows (id, title, severity, status,
|
|
5
|
+
* resolution). When an action returns 423 action_blocked_by_open_item, the
|
|
6
|
+
* matching blocker rows are highlighted so the user sees exactly which open
|
|
7
|
+
* item(s) gate the action they tried.
|
|
8
|
+
*/
|
|
9
|
+
import type React from "react";
|
|
10
|
+
import type { BlockerV1 } from "../../types/setup-cortex";
|
|
11
|
+
import { styles } from "./CortexSetupStyles";
|
|
12
|
+
|
|
13
|
+
function severityColor(severity: BlockerV1["severity"]): string {
|
|
14
|
+
switch (severity) {
|
|
15
|
+
case "blocker":
|
|
16
|
+
return "#f44336";
|
|
17
|
+
case "high":
|
|
18
|
+
return "#ff9800";
|
|
19
|
+
default:
|
|
20
|
+
return "#a0a0c0";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function CortexBlockersCard({
|
|
25
|
+
blockers,
|
|
26
|
+
highlight,
|
|
27
|
+
}: {
|
|
28
|
+
blockers: BlockerV1[];
|
|
29
|
+
highlight?: string[];
|
|
30
|
+
}): React.ReactElement {
|
|
31
|
+
const highlighted = highlight ?? [];
|
|
32
|
+
return (
|
|
33
|
+
<div style={styles.section}>
|
|
34
|
+
<h3 style={styles.sectionTitle}>
|
|
35
|
+
Open Hard-Gate Blockers
|
|
36
|
+
<span style={{ ...styles.badge, background: "#3a1a1a", color: "#f44336" }}>
|
|
37
|
+
{blockers.length}
|
|
38
|
+
</span>
|
|
39
|
+
</h3>
|
|
40
|
+
{blockers.length === 0 && (
|
|
41
|
+
<p style={{ color: "#4caf50", fontSize: "0.85rem" }}>
|
|
42
|
+
No open hard-gate blockers.
|
|
43
|
+
</p>
|
|
44
|
+
)}
|
|
45
|
+
{blockers.map((b) => {
|
|
46
|
+
const isHighlighted = highlighted.includes(b.id);
|
|
47
|
+
return (
|
|
48
|
+
<div
|
|
49
|
+
key={b.id}
|
|
50
|
+
style={{
|
|
51
|
+
...styles.blockerRow,
|
|
52
|
+
...(isHighlighted ? styles.blockerRowHighlighted : {}),
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
<span style={{ ...styles.mono, fontWeight: 700 }}>{b.id}</span>
|
|
56
|
+
<span style={{ flex: 1, color: "#e0e0e0" }}>{b.title}</span>
|
|
57
|
+
<span style={{ color: severityColor(b.severity) }}>
|
|
58
|
+
{b.severity}
|
|
59
|
+
</span>
|
|
60
|
+
<span style={{ color: "#a0a0c0", fontStyle: "italic" }}>
|
|
61
|
+
{isHighlighted ? "gates this action" : b.status}
|
|
62
|
+
</span>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
})}
|
|
66
|
+
{highlighted.length > 0 && (
|
|
67
|
+
<div style={styles.blocked}>
|
|
68
|
+
<strong>Blocked:</strong> the requested action is gated by the
|
|
69
|
+
highlighted open hard-gate item(s). It was not run.
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SetupTab/CortexEncoderCard.tsx — encoder gate status card (VC9C).
|
|
3
|
+
*
|
|
4
|
+
* Projects the VC9A reader status: effective triad mode A/B/C, asset digest
|
|
5
|
+
* prefix, qualification verdict + threshold failures, and encoder health. The
|
|
6
|
+
* header carries the shared VcStatusBadge driven by the payload's status field
|
|
7
|
+
* (VC0E honest-status pattern). Pure projection of the polled payload — never
|
|
8
|
+
* payload bytes/prompts/ledger.
|
|
9
|
+
*/
|
|
10
|
+
import type React from "react";
|
|
11
|
+
import type { SetupCortexStatusResponse } from "../../types/setup-cortex";
|
|
12
|
+
import { VcStatusBadge } from "../VcStatusBadge";
|
|
13
|
+
import { styles } from "./CortexSetupStyles";
|
|
14
|
+
|
|
15
|
+
function modeLabel(mode: "A" | "B" | "C" | undefined): string {
|
|
16
|
+
switch (mode) {
|
|
17
|
+
case "A":
|
|
18
|
+
return "A — qualified learned encoder asset";
|
|
19
|
+
case "B":
|
|
20
|
+
return "B — demoted (heuristic/trigram)";
|
|
21
|
+
case "C":
|
|
22
|
+
return "C — absent (asset not verified)";
|
|
23
|
+
default:
|
|
24
|
+
return "—";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function verdictBadge(
|
|
29
|
+
verdict: "qualified" | "demoted" | "unavailable" | undefined,
|
|
30
|
+
): React.ReactElement {
|
|
31
|
+
const bg =
|
|
32
|
+
verdict === "qualified"
|
|
33
|
+
? "#1a5a1a"
|
|
34
|
+
: verdict === "demoted"
|
|
35
|
+
? "#3a3a1a"
|
|
36
|
+
: "#3a1a1a";
|
|
37
|
+
const color =
|
|
38
|
+
verdict === "qualified"
|
|
39
|
+
? "#4caf50"
|
|
40
|
+
: verdict === "demoted"
|
|
41
|
+
? "#ffcc00"
|
|
42
|
+
: "#f44336";
|
|
43
|
+
return (
|
|
44
|
+
<span style={{ ...styles.badge, background: bg, color }}>
|
|
45
|
+
{verdict ?? "unknown"}
|
|
46
|
+
</span>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function CortexEncoderCard({
|
|
51
|
+
data,
|
|
52
|
+
error,
|
|
53
|
+
}: {
|
|
54
|
+
data: SetupCortexStatusResponse | null;
|
|
55
|
+
error: string | null;
|
|
56
|
+
}): React.ReactElement {
|
|
57
|
+
return (
|
|
58
|
+
<div style={styles.section}>
|
|
59
|
+
<h3 style={styles.sectionTitle}>
|
|
60
|
+
<span style={{ marginRight: "0.5rem" }}>Cortex Encoder</span>
|
|
61
|
+
<VcStatusBadge status={data?.status} />
|
|
62
|
+
</h3>
|
|
63
|
+
|
|
64
|
+
{error && (
|
|
65
|
+
<p style={{ color: "#f44336", fontSize: "0.85rem" }}>Error: {error}</p>
|
|
66
|
+
)}
|
|
67
|
+
{!data && !error && (
|
|
68
|
+
<p style={{ color: "#888", fontSize: "0.85rem" }}>
|
|
69
|
+
Loading cortex status...
|
|
70
|
+
</p>
|
|
71
|
+
)}
|
|
72
|
+
{!data?.enabled && (
|
|
73
|
+
<p style={{ color: "#f44336", fontSize: "0.85rem" }}>
|
|
74
|
+
Cortex status disabled (VC9A off).
|
|
75
|
+
</p>
|
|
76
|
+
)}
|
|
77
|
+
|
|
78
|
+
<div style={styles.row}>
|
|
79
|
+
<span style={styles.label}>Mode:</span>
|
|
80
|
+
<span style={styles.value}>{modeLabel(data?.encoderHealth.mode)}</span>
|
|
81
|
+
</div>
|
|
82
|
+
<div style={styles.row}>
|
|
83
|
+
<span style={styles.label}>Asset digest prefix:</span>
|
|
84
|
+
<span style={{ ...styles.value, ...styles.mono }}>
|
|
85
|
+
{data?.assetDigestPrefix ?? (
|
|
86
|
+
<span style={{ color: "#888" }}>not available</span>
|
|
87
|
+
)}
|
|
88
|
+
</span>
|
|
89
|
+
</div>
|
|
90
|
+
<div style={styles.row}>
|
|
91
|
+
<span style={styles.label}>Qualification:</span>
|
|
92
|
+
{verdictBadge(data?.qualification.verdict)}
|
|
93
|
+
</div>
|
|
94
|
+
{(data?.qualification.thresholdFailures.length ?? 0) > 0 && (
|
|
95
|
+
<div style={styles.warning}>
|
|
96
|
+
<strong>Threshold failure(s):</strong>{" "}
|
|
97
|
+
{data?.qualification.thresholdFailures.join(", ")}
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
{data?.status === "awaiting_data" && (
|
|
101
|
+
<p style={{ color: "#a0a0c0", fontSize: "0.85rem" }}>
|
|
102
|
+
Awaiting encoder data. Qualification will appear once an asset is
|
|
103
|
+
present.
|
|
104
|
+
</p>
|
|
105
|
+
)}
|
|
106
|
+
{data?.status === "deferred" && (
|
|
107
|
+
<p style={{ color: "#a0a0c0", fontSize: "0.85rem" }}>
|
|
108
|
+
Encoder status deferred.
|
|
109
|
+
</p>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SetupTab/CortexSetup.tsx — Setup Cortex sub-tab wizard shell (VC9C).
|
|
3
|
+
*
|
|
4
|
+
* Composes the encoder / blockers / actions cards. Polls the VC9A status via
|
|
5
|
+
* useSetupCortexPoll (5s, best-effort) and shares one blocked-highlight set:
|
|
6
|
+
* when an action returns 423 action_blocked_by_open_item, the gating blocker
|
|
7
|
+
* rows are highlighted on the blockers card.
|
|
8
|
+
*
|
|
9
|
+
* Pure consumer of the VC9A status + VC9B action endpoints — NO server logic.
|
|
10
|
+
*/
|
|
11
|
+
import type React from "react";
|
|
12
|
+
import { useState, useCallback } from "react";
|
|
13
|
+
import { useSetupCortexPoll } from "../useSetupCortexPoll";
|
|
14
|
+
import { CortexEncoderCard } from "./CortexEncoderCard";
|
|
15
|
+
import { CortexBlockersCard } from "./CortexBlockersCard";
|
|
16
|
+
import { CortexActionsCard } from "./CortexActionsCard";
|
|
17
|
+
import { styles } from "./CortexSetupStyles";
|
|
18
|
+
|
|
19
|
+
export default function CortexSetup(): React.ReactElement {
|
|
20
|
+
const [state, poll] = useSetupCortexPoll();
|
|
21
|
+
const [highlight, setHighlight] = useState<string[]>([]);
|
|
22
|
+
|
|
23
|
+
const onBlocked = useCallback((blockerIds: string[]) => {
|
|
24
|
+
setHighlight(blockerIds);
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
const onAction = useCallback(() => {
|
|
28
|
+
poll();
|
|
29
|
+
}, [poll]);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div style={styles.container}>
|
|
33
|
+
<h2 style={{ fontSize: "1.3rem", marginTop: 0, marginBottom: "1rem" }}>
|
|
34
|
+
Setup Cortex
|
|
35
|
+
</h2>
|
|
36
|
+
<p style={{ fontSize: "0.85rem", color: "#a0a0c0", marginTop: 0 }}>
|
|
37
|
+
Vector-cortex encoder gate: mode, qualification, open hard-gate
|
|
38
|
+
blockers, and the confirmation-gated fetch/bench/verify actions.
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
<CortexEncoderCard data={state.data} error={state.error} />
|
|
42
|
+
<CortexBlockersCard
|
|
43
|
+
blockers={state.data?.blockers ?? []}
|
|
44
|
+
highlight={highlight}
|
|
45
|
+
/>
|
|
46
|
+
<CortexActionsCard
|
|
47
|
+
data={state.data}
|
|
48
|
+
onBlocked={onBlocked}
|
|
49
|
+
onAction={onAction}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SetupTab/CortexSetupStyles.ts — shared styles for the CortexSetup sub-tab.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors EmbedderSetupStyles conventions so the Setup Cortex sub-tab reads
|
|
5
|
+
* like the rest of the Setup tab. Split out so each Cortex card stays well
|
|
6
|
+
* under the extensions/ soft line limit.
|
|
7
|
+
*/
|
|
8
|
+
import type React from "react";
|
|
9
|
+
|
|
10
|
+
export const styles: Record<string, React.CSSProperties> = {
|
|
11
|
+
container: {
|
|
12
|
+
padding: "1rem",
|
|
13
|
+
maxWidth: "720px",
|
|
14
|
+
margin: "0 auto",
|
|
15
|
+
fontFamily: "system-ui, sans-serif",
|
|
16
|
+
color: "#e0e0e0",
|
|
17
|
+
},
|
|
18
|
+
section: {
|
|
19
|
+
background: "#1a1a2e",
|
|
20
|
+
borderRadius: "8px",
|
|
21
|
+
padding: "1rem",
|
|
22
|
+
marginBottom: "1rem",
|
|
23
|
+
border: "1px solid #2a2a4e",
|
|
24
|
+
},
|
|
25
|
+
sectionTitle: {
|
|
26
|
+
fontSize: "1.1rem",
|
|
27
|
+
fontWeight: 700,
|
|
28
|
+
marginTop: 0,
|
|
29
|
+
marginBottom: "0.75rem",
|
|
30
|
+
color: "#e0e0e0",
|
|
31
|
+
borderBottom: "1px solid #333",
|
|
32
|
+
paddingBottom: "0.5rem",
|
|
33
|
+
},
|
|
34
|
+
label: { fontWeight: 600, color: "#a0a0c0", marginRight: "0.5rem" },
|
|
35
|
+
value: { color: "#e0e0e0" },
|
|
36
|
+
row: { marginBottom: "0.4rem", fontSize: "0.9rem" },
|
|
37
|
+
warning: {
|
|
38
|
+
background: "#3a2a00",
|
|
39
|
+
border: "1px solid #665500",
|
|
40
|
+
borderRadius: "8px",
|
|
41
|
+
padding: "0.75rem",
|
|
42
|
+
marginTop: "0.5rem",
|
|
43
|
+
color: "#ffcc00",
|
|
44
|
+
fontSize: "0.85rem",
|
|
45
|
+
},
|
|
46
|
+
blocked: {
|
|
47
|
+
background: "#3a1a1a",
|
|
48
|
+
border: "1px solid #662222",
|
|
49
|
+
borderRadius: "8px",
|
|
50
|
+
padding: "0.75rem",
|
|
51
|
+
marginTop: "0.5rem",
|
|
52
|
+
color: "#ff6666",
|
|
53
|
+
fontSize: "0.85rem",
|
|
54
|
+
},
|
|
55
|
+
badge: {
|
|
56
|
+
display: "inline-block",
|
|
57
|
+
padding: "0.15rem 0.5rem",
|
|
58
|
+
borderRadius: "4px",
|
|
59
|
+
fontSize: "0.8rem",
|
|
60
|
+
fontWeight: 600,
|
|
61
|
+
marginLeft: "0.5rem",
|
|
62
|
+
},
|
|
63
|
+
button: {
|
|
64
|
+
background: "#3a5a9f",
|
|
65
|
+
color: "#fff",
|
|
66
|
+
border: "none",
|
|
67
|
+
borderRadius: "6px",
|
|
68
|
+
padding: "0.5rem 1rem",
|
|
69
|
+
cursor: "pointer",
|
|
70
|
+
fontSize: "0.9rem",
|
|
71
|
+
fontWeight: 600,
|
|
72
|
+
},
|
|
73
|
+
buttonDanger: {
|
|
74
|
+
background: "#6a2a2a",
|
|
75
|
+
color: "#ffb3b3",
|
|
76
|
+
border: "1px solid #662222",
|
|
77
|
+
borderRadius: "6px",
|
|
78
|
+
padding: "0.5rem 1rem",
|
|
79
|
+
cursor: "pointer",
|
|
80
|
+
fontSize: "0.9rem",
|
|
81
|
+
fontWeight: 600,
|
|
82
|
+
},
|
|
83
|
+
blockerRow: {
|
|
84
|
+
display: "flex",
|
|
85
|
+
justifyContent: "space-between",
|
|
86
|
+
alignItems: "center",
|
|
87
|
+
gap: "0.5rem",
|
|
88
|
+
padding: "0.5rem 0.6rem",
|
|
89
|
+
borderRadius: "6px",
|
|
90
|
+
marginBottom: "0.35rem",
|
|
91
|
+
fontSize: "0.85rem",
|
|
92
|
+
},
|
|
93
|
+
blockerRowHighlighted: {
|
|
94
|
+
background: "#3a1a1a",
|
|
95
|
+
border: "1px solid #662222",
|
|
96
|
+
},
|
|
97
|
+
mono: { fontFamily: "ui-monospace, monospace", fontSize: "0.8rem" },
|
|
98
|
+
};
|
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dashboard-client/src/tabs/SetupTab.tsx — Setup wizard tab shell (P0b).
|
|
3
3
|
*
|
|
4
|
-
* Sub-tab shell routing between Embedder / Config / Game Mode /
|
|
5
|
-
* The embedder setup section lives in
|
|
4
|
+
* Sub-tab shell routing between Embedder / Thresholds / Config / Game Mode /
|
|
5
|
+
* Achievements / Cortex. The embedder setup section lives in
|
|
6
|
+
* SetupTab/EmbedderSetup.tsx; the VC9C Cortex sub-tab lives in
|
|
7
|
+
* SetupTab/CortexSetup.tsx.
|
|
6
8
|
*
|
|
7
9
|
* PREVENT-PI-004: all data comes from localhost dashboard API endpoints —
|
|
8
10
|
* no external network calls.
|
|
9
11
|
*/
|
|
10
12
|
import type React from "react";
|
|
11
|
-
import { useState } from "react";
|
|
13
|
+
import { useState, useMemo } from "react";
|
|
12
14
|
import GameTab from "./GameTab";
|
|
13
15
|
import AchievementsTab from "./AchievementsTab";
|
|
14
16
|
import ConfigTab from "./ConfigTab";
|
|
15
17
|
import EmbedderSetup from "./SetupTab/EmbedderSetup";
|
|
16
18
|
import ThresholdsPanel from "./SetupTab/ThresholdsPanel";
|
|
19
|
+
import CortexSetup from "./SetupTab/CortexSetup";
|
|
17
20
|
import { Toggle } from "../components/ui/toggle";
|
|
21
|
+
import { useSetupCortexPoll, isCortexSubTabVisible } from "./useSetupCortexPoll";
|
|
18
22
|
|
|
19
23
|
type SetupSubTab =
|
|
20
24
|
| "embedder"
|
|
21
25
|
| "thresholds"
|
|
22
26
|
| "config"
|
|
23
27
|
| "game"
|
|
24
|
-
| "achievements"
|
|
28
|
+
| "achievements"
|
|
29
|
+
| "cortex";
|
|
25
30
|
|
|
26
|
-
const
|
|
31
|
+
const BASE_SUB_TABS: ReadonlyArray<{ id: SetupSubTab; label: string }> = [
|
|
27
32
|
{ id: "embedder", label: "Embedder" },
|
|
28
33
|
{ id: "thresholds", label: "Thresholds" },
|
|
29
34
|
{ id: "config", label: "Config" },
|
|
@@ -31,8 +36,18 @@ const SUB_TABS: ReadonlyArray<{ id: SetupSubTab; label: string }> = [
|
|
|
31
36
|
{ id: "achievements", label: "Achievements" },
|
|
32
37
|
];
|
|
33
38
|
|
|
39
|
+
/** The Cortex sub-tab is filtered out when VC9A reports the off/disabled shape. */
|
|
40
|
+
const CORTEX_TAB = { id: "cortex", label: "Cortex" } as const;
|
|
41
|
+
|
|
34
42
|
export default function SetupTab(): React.ReactElement {
|
|
35
43
|
const [subTab, setSubTab] = useState<SetupSubTab>("embedder");
|
|
44
|
+
const [cortex] = useSetupCortexPoll();
|
|
45
|
+
|
|
46
|
+
const subTabs = useMemo(() => {
|
|
47
|
+
const tabs = [...BASE_SUB_TABS];
|
|
48
|
+
if (isCortexSubTabVisible(cortex.data)) tabs.push(CORTEX_TAB);
|
|
49
|
+
return tabs;
|
|
50
|
+
}, [cortex.data]);
|
|
36
51
|
|
|
37
52
|
return (
|
|
38
53
|
<div className="mx-auto flex max-w-3xl flex-col gap-4 p-4">
|
|
@@ -40,7 +55,7 @@ export default function SetupTab(): React.ReactElement {
|
|
|
40
55
|
className="flex gap-2 border-b border-border pb-2"
|
|
41
56
|
aria-label="Setup sections"
|
|
42
57
|
>
|
|
43
|
-
{
|
|
58
|
+
{subTabs.map((t) => (
|
|
44
59
|
<Toggle
|
|
45
60
|
key={t.id}
|
|
46
61
|
pressed={subTab === t.id}
|
|
@@ -56,6 +71,7 @@ export default function SetupTab(): React.ReactElement {
|
|
|
56
71
|
{subTab === "config" && <ConfigTab />}
|
|
57
72
|
{subTab === "game" && <GameTab />}
|
|
58
73
|
{subTab === "achievements" && <AchievementsTab />}
|
|
74
|
+
{subTab === "cortex" && <CortexSetup />}
|
|
59
75
|
</div>
|
|
60
76
|
);
|
|
61
77
|
}
|