create-principles-disciple 1.145.43 → 1.146.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_release/product-identity.json +2 -2
- package/console/dist/server/routes/examiner-executor.d.ts +8 -2
- package/console/dist/server/routes/examiner-executor.js +10 -4
- package/console/dist/server/routes/examiner.d.ts +23 -17
- package/console/dist/server/routes/examiner.js +30 -27
- package/console/dist/ui/App.js +1 -1
- package/console/dist/ui/components/layout/app-sidebar.d.ts +3 -4
- package/console/dist/ui/components/layout/app-sidebar.js +5 -7
- package/console/dist/ui/i18n/en.json +1 -1
- package/console/dist/ui/i18n/zh-CN.json +1 -1
- package/console/dist/ui/utils/runtime-mode.d.ts +2 -1
- package/console/dist/ui/utils/runtime-mode.js +2 -1
- package/console/dist/web/assets/app.js +23 -23
- package/console/lab/lib/challenge-actor.mjs +394 -0
- package/console/lab/lib/challenge-arms.mjs +102 -0
- package/console/lab/lib/challenge-behavior-report.mjs +2484 -0
- package/console/lab/lib/challenge-compile.mjs +211 -0
- package/console/lab/lib/challenge-freeze.mjs +215 -0
- package/console/lab/lib/challenge-isolation-probe.mjs +550 -0
- package/console/lab/lib/challenge-ledger.mjs +206 -0
- package/console/lab/lib/challenge-openclaw-host.mjs +630 -0
- package/console/lab/lib/challenge-runner.mjs +868 -0
- package/console/lab/lib/challenge-stage-r-gate.mjs +458 -0
- package/console/lab/lib/challenge-statistics.mjs +591 -0
- package/console/lab/lib/claim-evidence-env.mjs +652 -0
- package/console/lab/lib/claim-evidence-scorer.mjs +784 -0
- package/console/lab/lib/examiner-injection-evidence.mjs +367 -0
- package/console/lab/lib/examiner-study.mjs +1203 -0
- package/console/lab/lib/examiner-v07-cases.mjs +187 -0
- package/console/lab/lib/examiner-v2-cases.mjs +61 -0
- package/console/lab/lib/fixture.mjs +382 -0
- package/console/lab/lib/g2.mjs +146 -0
- package/console/lab/lib/host-actor.mjs +987 -0
- package/console/lab/lib/sidecar.mjs +273 -0
- package/package.json +1 -1
- package/release-manager/package.json +1 -1
|
@@ -90,8 +90,14 @@ export declare function canonicalPathSync(target: string): string | null;
|
|
|
90
90
|
export declare function isSamePath(a: string, b: string): boolean;
|
|
91
91
|
/** Strict containment: equal paths are NOT inside each other. */
|
|
92
92
|
export declare function isPathInside(root: string, candidate: string): boolean;
|
|
93
|
-
/**
|
|
94
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Resolve the two roots once. Console-created studies are WORKSPACE DATA, not
|
|
95
|
+
* repository content: they default to `<dataRoot>/studies`, where the caller
|
|
96
|
+
* passes `<workspace>/.pd/examiner`. `PD_EXAMINER_STUDIES_ROOT` overrides the
|
|
97
|
+
* WRITABLE root only (tests / operators). The historical research assets ship
|
|
98
|
+
* with the lab payload (absent in an installation → an empty read-only list).
|
|
99
|
+
*/
|
|
100
|
+
export declare function resolveStudyRoots(labRoot: string, dataRoot: string): StudyRoots;
|
|
95
101
|
export declare function isJsonObject(value: unknown): value is Record<string, unknown>;
|
|
96
102
|
/** Boundary-checked study file reader (fails closed on missing/malformed). */
|
|
97
103
|
export declare function readStudyJson(studyDir: string, rel: string): Record<string, unknown>;
|
|
@@ -69,10 +69,16 @@ export function isPathInside(root, candidate) {
|
|
|
69
69
|
const prefix = r.endsWith(path.sep) ? r : `${r}${path.sep}`;
|
|
70
70
|
return c !== r && c.startsWith(prefix);
|
|
71
71
|
}
|
|
72
|
-
/**
|
|
73
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the two roots once. Console-created studies are WORKSPACE DATA, not
|
|
74
|
+
* repository content: they default to `<dataRoot>/studies`, where the caller
|
|
75
|
+
* passes `<workspace>/.pd/examiner`. `PD_EXAMINER_STUDIES_ROOT` overrides the
|
|
76
|
+
* WRITABLE root only (tests / operators). The historical research assets ship
|
|
77
|
+
* with the lab payload (absent in an installation → an empty read-only list).
|
|
78
|
+
*/
|
|
79
|
+
export function resolveStudyRoots(labRoot, dataRoot) {
|
|
74
80
|
const override = process.env.PD_EXAMINER_STUDIES_ROOT;
|
|
75
|
-
const writable = override ? path.resolve(override) : path.join(path.resolve(
|
|
81
|
+
const writable = override ? path.resolve(override) : path.join(path.resolve(dataRoot), 'studies');
|
|
76
82
|
const historical = path.join(path.resolve(labRoot), 'examiner-studies');
|
|
77
83
|
// Canonical forms when resolvable; the unresolved form is kept so the
|
|
78
84
|
// boundary gates below can fail closed with a stable reason.
|
|
@@ -571,7 +577,7 @@ export async function materializeConsoleStudy(modules, labRoot, roots, selection
|
|
|
571
577
|
* never real-host behavior.
|
|
572
578
|
*/
|
|
573
579
|
export async function materializeOfflineStudy(modules, labRoot, inputs) {
|
|
574
|
-
const fixtureUrl = pathToFileURL(path.join(labRoot, '
|
|
580
|
+
const fixtureUrl = pathToFileURL(path.join(labRoot, 'lib', 'examiner-v07-cases.mjs')).href;
|
|
575
581
|
const fixture = (await import(fixtureUrl));
|
|
576
582
|
const freezeUrl = pathToFileURL(path.join(labRoot, 'lib', 'challenge-freeze.mjs')).href;
|
|
577
583
|
const freeze = (await import(freezeUrl));
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Product entry for the Examiner research pipeline on top of the existing
|
|
5
5
|
* principle-learning-lab (single research engine — no parallel Runner/Ledger/
|
|
6
|
-
* Scorer/Report).
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Scorer/Report). The lab runtime subset ships WITH the console payload
|
|
7
|
+
* (`console/lab`), so this surface is available in an installed runtime; a
|
|
8
|
+
* developer checkout is served from the repository's scripts/dev/ lab.
|
|
9
|
+
*
|
|
10
|
+
* Offline only: every study carries SYNTHETIC_OFFLINE gold and is executed by
|
|
11
|
+
* the deterministic local stub. Real model calls and real host runs stay
|
|
12
|
+
* behind the Owner-authorization / Stage R gate and are refused here.
|
|
10
13
|
*
|
|
11
14
|
* Surface (all offline, zero real model/host calls):
|
|
12
15
|
* GET /api/v1/examiner/overview — gates, host capability, study list
|
|
@@ -26,21 +29,24 @@
|
|
|
26
29
|
* the experiment mode as a boolean. No request string crosses into the
|
|
27
30
|
* research pipeline, and no request value constructs a path.
|
|
28
31
|
*
|
|
29
|
-
* Two roots (P1-1): NEW console studies are written under
|
|
30
|
-
*
|
|
31
|
-
* the committed `examiner-studies/` research assets
|
|
32
|
-
* read-only here (POST /run and
|
|
33
|
-
* `challenge-studies/` area is never a
|
|
34
|
-
* refused by this route class itself.
|
|
32
|
+
* Two roots (P1-1): NEW console studies are WORKSPACE DATA — written under
|
|
33
|
+
* `<workspace>/.pd/examiner/studies` — and require the server's own ownership
|
|
34
|
+
* marker; the committed `examiner-studies/` research assets that travel with
|
|
35
|
+
* the lab payload are visible but ALWAYS read-only here (POST /run and
|
|
36
|
+
* POST /report answer 403). The frozen `challenge-studies/` area is never a
|
|
37
|
+
* write target. Real-host execution is refused by this route class itself.
|
|
35
38
|
*/
|
|
36
39
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
37
40
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* Locate the principle-learning-lab payload. Two layouts are legitimate and
|
|
42
|
+
* both are resolved from THIS module's own location — never from a request:
|
|
43
|
+
*
|
|
44
|
+
* installed <console>/lab (shipped by the installer)
|
|
45
|
+
* repository <repo>/scripts/dev/principle-learning-lab
|
|
46
|
+
*
|
|
47
|
+
* `PD_EXAMINER_LAB_ROOT` overrides both (operators / tests). A candidate only
|
|
48
|
+
* counts when the lab entry module is actually present, so a half-copied
|
|
49
|
+
* payload fails closed into the 503 branch instead of half-working.
|
|
44
50
|
*/
|
|
45
|
-
export declare function
|
|
51
|
+
export declare function resolveLabRoot(moduleUrl: string, env?: Record<string, string | undefined>): string | null;
|
|
46
52
|
export declare function handleExaminerRoute(req: IncomingMessage, res: ServerResponse, workspaceDir: string, subPath: string): Promise<void>;
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { fileURLToPath } from 'node:url';
|
|
3
4
|
import { sendSuccess, sendError, sendNotFound } from '../utils/response.js';
|
|
4
5
|
import { PrinciplesConsoleModel } from '../models/PrinciplesConsoleModel.js';
|
|
5
6
|
import { loadLabModules, loadHostCapability, preflightCheck, offlineStudyPass, reportMaterialize, listStudyNames, resolveStudyAccess, resolveStudyRoots, studyStatusPayload, studyReportPayload, materializeConsoleStudy, verifyConsoleOwnership, writableRootProblem, isJsonObject, ExaminerPreflightBlockedError, } from './examiner-executor.js';
|
|
6
7
|
/* eslint-disable @typescript-eslint/max-params -- node:http handler signature (req, res, workspaceDir, subPath) matches every other route */
|
|
7
|
-
const
|
|
8
|
-
const repoRoot = path.resolve(here, '..', '..', '..', '..', '..');
|
|
9
|
-
const labRoot = path.join(repoRoot, 'scripts', 'dev', 'principle-learning-lab');
|
|
8
|
+
const LAB_ENTRY = path.join('lib', 'examiner-study.mjs');
|
|
10
9
|
const PRINCIPLE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
11
10
|
const STUDY_ROUTE_PATTERN = /^\/studies\/([A-Za-z0-9-]+)(\/[^/]*)?$/;
|
|
12
11
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
12
|
+
* Locate the principle-learning-lab payload. Two layouts are legitimate and
|
|
13
|
+
* both are resolved from THIS module's own location — never from a request:
|
|
14
|
+
*
|
|
15
|
+
* installed <console>/lab (shipped by the installer)
|
|
16
|
+
* repository <repo>/scripts/dev/principle-learning-lab
|
|
17
|
+
*
|
|
18
|
+
* `PD_EXAMINER_LAB_ROOT` overrides both (operators / tests). A candidate only
|
|
19
|
+
* counts when the lab entry module is actually present, so a half-copied
|
|
20
|
+
* payload fails closed into the 503 branch instead of half-working.
|
|
19
21
|
*/
|
|
20
|
-
export function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return isExaminerDevRuntime(import.meta.url);
|
|
22
|
+
export function resolveLabRoot(moduleUrl, env = process.env) {
|
|
23
|
+
const here = path.dirname(fileURLToPath(moduleUrl));
|
|
24
|
+
const candidates = [
|
|
25
|
+
env.PD_EXAMINER_LAB_ROOT ? path.resolve(env.PD_EXAMINER_LAB_ROOT) : null,
|
|
26
|
+
path.resolve(here, '..', '..', '..', 'lab'),
|
|
27
|
+
path.resolve(here, '..', '..', '..', '..', '..', 'scripts', 'dev', 'principle-learning-lab'),
|
|
28
|
+
].filter((candidate) => candidate !== null);
|
|
29
|
+
return candidates.find((candidate) => fs.existsSync(path.join(candidate, LAB_ENTRY))) ?? null;
|
|
29
30
|
}
|
|
31
|
+
const labRoot = resolveLabRoot(import.meta.url);
|
|
30
32
|
/** The runner's lock-time re-verification refusal (dynamic module: match the
|
|
31
33
|
* contract name, not an instanceof across import boundaries). */
|
|
32
34
|
function isFrozenStudyDriftError(error) {
|
|
@@ -64,6 +66,10 @@ let labUnavailableReason = null;
|
|
|
64
66
|
async function loadLab() {
|
|
65
67
|
if (hostCapability)
|
|
66
68
|
return hostCapability;
|
|
69
|
+
if (!labRoot) {
|
|
70
|
+
labUnavailableReason = 'the principle-learning-lab payload was not found (expected <console>/lab or the repository scripts/dev lab)';
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
67
73
|
try {
|
|
68
74
|
labModules = await loadLabModules(labRoot);
|
|
69
75
|
hostCapability = await loadHostCapability(labRoot);
|
|
@@ -99,17 +105,13 @@ function readBody(req) {
|
|
|
99
105
|
});
|
|
100
106
|
}
|
|
101
107
|
export async function handleExaminerRoute(req, res, workspaceDir, subPath) {
|
|
102
|
-
if (!examinerDevEnabled()) {
|
|
103
|
-
sendError(res, 404, 'examiner_not_enabled', 'The Examiner research surface is a local-dev capability and is not enabled in this runtime');
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
108
|
const lab = await loadLab();
|
|
107
|
-
if (!lab || !labModules) {
|
|
108
|
-
sendError(res, 503, '
|
|
109
|
+
if (!lab || !labModules || !labRoot) {
|
|
110
|
+
sendError(res, 503, 'examiner_lab_unavailable', `the Examiner research engine could not be loaded from this installation: ${labUnavailableReason ?? 'unknown reason'}`);
|
|
109
111
|
return;
|
|
110
112
|
}
|
|
111
113
|
const method = req.method ?? 'GET';
|
|
112
|
-
const roots = resolveStudyRoots(labRoot);
|
|
114
|
+
const roots = resolveStudyRoots(labRoot, path.join(workspaceDir, '.pd', 'examiner'));
|
|
113
115
|
const context = { labRoot, roots };
|
|
114
116
|
const rootProblem = writableRootProblem(roots);
|
|
115
117
|
// GET /overview
|
|
@@ -118,17 +120,18 @@ export async function handleExaminerRoute(req, res, workspaceDir, subPath) {
|
|
|
118
120
|
const historical = listStudyNames(roots.historical);
|
|
119
121
|
sendSuccess(res, {
|
|
120
122
|
spec: 'SPEC-PD-EXAMINER-001 v0.9',
|
|
121
|
-
executionScope: 'offline-stub only —
|
|
123
|
+
executionScope: 'offline-stub only — every study uses SYNTHETIC_OFFLINE gold and the deterministic local stub; this panel validates the research contract, never real host behavior',
|
|
122
124
|
gates: {
|
|
123
125
|
gate1_challenge_trust: 'BLOCKED — independent human Gold review has not been performed for any Examiner suite (code tests can never substitute)',
|
|
124
126
|
gate2_behavior_evaluation: 'NOT_READY — requires Gate 1 + real-host authorization',
|
|
125
127
|
gate3_llm_authoring: 'NOT_STARTED',
|
|
126
|
-
gate4_product_integration: '
|
|
128
|
+
gate4_product_integration: 'ACTIVE — the offline research panel (create / run / report) ships with the console; real model calls and real host runs stay refused under this gate',
|
|
127
129
|
},
|
|
128
130
|
hostInjectionCapability: lab,
|
|
129
131
|
fullConclusionMinimumLevel: 'CONTEXT_PRESENT',
|
|
130
132
|
writableStudiesRoot: roots.writable,
|
|
131
133
|
historicalStudiesRoot: roots.historical,
|
|
134
|
+
studiesAreWorkspaceData: true,
|
|
132
135
|
rootProblem,
|
|
133
136
|
studies: [...writable, ...historical.filter((name) => !writable.includes(name))],
|
|
134
137
|
readOnlyStudies: [
|
package/console/dist/ui/App.js
CHANGED
|
@@ -165,7 +165,7 @@ function AuthRoutes() {
|
|
|
165
165
|
}, []);
|
|
166
166
|
return (_jsxs(Routes, { children: [_jsx(Route, { path: "/splash", element: _jsx(SplashScreen, { onComplete: () => {
|
|
167
167
|
setShowSplash(false);
|
|
168
|
-
} }) }), _jsx(Route, { path: "/login", element: _jsx(LoginForm, { onAuthSuccess: handleAuthSuccess }) }), _jsx(Route, { path: "/*", element: authed === null ? (_jsx("div", { className: "min-h-screen bg-paper flex items-center justify-center", children: _jsxs("div", { className: "flex flex-col items-center gap-4", children: [_jsx("div", { className: "w-8 h-8 border-2 border-gov border-t-transparent rounded-full animate-spin" }), _jsx("span", { className: "text-[12px] font-mono tracking-wider text-ink-3 uppercase", children: "Verifying Session..." })] }) })) : authed ? (_jsx(NotificationProvider, { children: _jsx(AuthenticatedShell, { featureFlags: featureFlags ?? undefined, children: _jsx(ErrorBoundary, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(Navigate, { to: "/focus", replace: true }) }), _jsx(Route, { path: "/welcome", element: _jsx(WelcomePage, { workspaceId: currentWorkspaceId }) }), _jsx(Route, { path: "/focus", element: _jsx(FocusPage, { featureFlags: featureFlags ?? undefined }) }), _jsx(Route, { path: "/pain", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/principles", element: _jsx(PrinciplesPage, {}) }), _jsx(Route, { path: "/principles/core", element: _jsx(CorePrinciplesPage, {}) }), _jsx(Route, { path: "/principles/:id", element: _jsx(PrincipleDetailPage, {}) }), _jsx(Route, { path: "/activation", element: _jsx(ActivationPage, {}) }), _jsx(Route, { path: "/debt", element: _jsx(DebtPage, {}) }),
|
|
168
|
+
} }) }), _jsx(Route, { path: "/login", element: _jsx(LoginForm, { onAuthSuccess: handleAuthSuccess }) }), _jsx(Route, { path: "/*", element: authed === null ? (_jsx("div", { className: "min-h-screen bg-paper flex items-center justify-center", children: _jsxs("div", { className: "flex flex-col items-center gap-4", children: [_jsx("div", { className: "w-8 h-8 border-2 border-gov border-t-transparent rounded-full animate-spin" }), _jsx("span", { className: "text-[12px] font-mono tracking-wider text-ink-3 uppercase", children: "Verifying Session..." })] }) })) : authed ? (_jsx(NotificationProvider, { children: _jsx(AuthenticatedShell, { featureFlags: featureFlags ?? undefined, children: _jsx(ErrorBoundary, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(Navigate, { to: "/focus", replace: true }) }), _jsx(Route, { path: "/welcome", element: _jsx(WelcomePage, { workspaceId: currentWorkspaceId }) }), _jsx(Route, { path: "/focus", element: _jsx(FocusPage, { featureFlags: featureFlags ?? undefined }) }), _jsx(Route, { path: "/pain", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/principles", element: _jsx(PrinciplesPage, {}) }), _jsx(Route, { path: "/principles/core", element: _jsx(CorePrinciplesPage, {}) }), _jsx(Route, { path: "/principles/:id", element: _jsx(PrincipleDetailPage, {}) }), _jsx(Route, { path: "/activation", element: _jsx(ActivationPage, {}) }), _jsx(Route, { path: "/debt", element: _jsx(DebtPage, {}) }), _jsx(Route, { path: "/examiner", element: _jsx(ExaminerPage, {}) }), _jsx(Route, { path: "/control-center", element: _jsx(ControlCenterPage, {}) }), _jsx(Route, { path: "/settings", element: _jsx(SettingsPage, {}) }), _jsx(Route, { path: "/update", element: _jsx(UpdatePage, {}) }), _jsx(Route, { path: "/report-problem", element: _jsx(ReportProblemPage, {}) }), _jsx(Route, { path: "/failed-tasks", element: _jsx(FailedTasksPage, {}) }), _jsx(Route, { path: "/intent", element: _jsx(IntentPage, {}) }), IS_DEV && (_jsx(Route, { path: "/design-system", element: _jsx(DesignSystemPage, {}) })), !IS_DEV && (_jsx(Route, { path: "/design-system", element: _jsx(Navigate, { to: "/focus", replace: true }) }))] }) }) }) })) : (_jsx(Navigate, { to: "/login", replace: true })) })] }));
|
|
169
169
|
}
|
|
170
170
|
export function App() {
|
|
171
171
|
return (_jsx(ThemeProvider, { children: _jsxs(I18nextProvider, { i18n: i18n, children: [_jsx(HashRouter, { children: _jsx(AuthRoutes, {}) }), _jsx(Toaster, {})] }) }));
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* capability the server refuses.
|
|
3
|
+
* The Examiner is a shipped product surface: the offline research panel ships
|
|
4
|
+
* with the console payload, so the navigation entry is build-mode independent.
|
|
6
5
|
*/
|
|
7
|
-
export declare function visibleMainNavItems(
|
|
6
|
+
export declare function visibleMainNavItems(): {
|
|
8
7
|
id: string;
|
|
9
8
|
labelKey: string;
|
|
10
9
|
href: string;
|
|
@@ -7,7 +7,6 @@ import { useTranslation } from "react-i18next";
|
|
|
7
7
|
import { useNotifications } from "../notifications/useNotifications.js";
|
|
8
8
|
import { clearToken } from "../../api.js";
|
|
9
9
|
import { cn } from "../../../lib/utils.js";
|
|
10
|
-
import { IS_DEV } from "../../utils/runtime-mode.js";
|
|
11
10
|
import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from "../ui/sheet.js";
|
|
12
11
|
function ThresholdMark({ className }) {
|
|
13
12
|
return (_jsxs("svg", { viewBox: "0 0 28 28", className: className, fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: [_jsx("path", { d: "M6 4V24M22 4V24M2 14H26", strokeLinecap: "square" }), _jsx("circle", { cx: "14", cy: "14", r: "2.5", fill: "currentColor", stroke: "none" })] }));
|
|
@@ -22,12 +21,11 @@ const mainNavItems = [
|
|
|
22
21
|
{ id: "intent", labelKey: "components.sidebar.intent", href: "/intent", icon: Compass },
|
|
23
22
|
];
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* capability the server refuses.
|
|
24
|
+
* The Examiner is a shipped product surface: the offline research panel ships
|
|
25
|
+
* with the console payload, so the navigation entry is build-mode independent.
|
|
28
26
|
*/
|
|
29
|
-
export function visibleMainNavItems(
|
|
30
|
-
return
|
|
27
|
+
export function visibleMainNavItems() {
|
|
28
|
+
return mainNavItems;
|
|
31
29
|
}
|
|
32
30
|
const toolNavItems = [
|
|
33
31
|
{ id: "control-center", labelKey: "components.sidebar.controlCenter", href: "/control-center", icon: Settings },
|
|
@@ -61,7 +59,7 @@ function SidebarContent({ featureFlags, onNavigate, touchTargets, }) {
|
|
|
61
59
|
i18n.changeLanguage(nextLang);
|
|
62
60
|
localStorage.setItem("pd-language", nextLang);
|
|
63
61
|
};
|
|
64
|
-
return (_jsxs(_Fragment, { children: [_jsxs("nav", { className: "flex-1 py-2 overflow-y-auto", "aria-label": t("components.sidebar.navigation", { defaultValue: "主导航" }), children: [_jsx("div", { className: "px-2", children: visibleMainNavItems(
|
|
62
|
+
return (_jsxs(_Fragment, { children: [_jsxs("nav", { className: "flex-1 py-2 overflow-y-auto", "aria-label": t("components.sidebar.navigation", { defaultValue: "主导航" }), children: [_jsx("div", { className: "px-2", children: visibleMainNavItems().map((item) => {
|
|
65
63
|
const Icon = item.icon;
|
|
66
64
|
const active = isActive(item.href);
|
|
67
65
|
return (_jsxs(Link, { to: item.href, "data-testid": `nav-${item.id}`, "aria-current": active ? "page" : undefined, onClick: onNavigate, className: cn("flex items-center gap-3 px-3 rounded-[var(--radius-sm)] text-[13px] transition-all duration-150", touchTargets ? "min-h-[44px] py-2" : "py-2", active
|
|
@@ -2076,7 +2076,7 @@
|
|
|
2076
2076
|
"runDone": "Offline execution finished: {{count}} units succeeded.",
|
|
2077
2077
|
"reportGenerated": "Report generated ({{status}}).",
|
|
2078
2078
|
"errors": {
|
|
2079
|
-
"unavailable": "Examiner
|
|
2079
|
+
"unavailable": "The Examiner research engine is unavailable in this installation (the installer payload does not include the research modules).",
|
|
2080
2080
|
"create": "Failed to create the study.",
|
|
2081
2081
|
"preflight": "Preflight failed.",
|
|
2082
2082
|
"run": "Offline execution failed.",
|
|
@@ -2076,7 +2076,7 @@
|
|
|
2076
2076
|
"runDone": "离线执行完成:{{count}} 个单元成功。",
|
|
2077
2077
|
"reportGenerated": "报告已生成({{status}})。",
|
|
2078
2078
|
"errors": {
|
|
2079
|
-
"unavailable": "Examiner
|
|
2079
|
+
"unavailable": "Examiner 研究引擎在此安装中不可用(安装包未包含研究模块)。",
|
|
2080
2080
|
"create": "创建 Study 失败。",
|
|
2081
2081
|
"preflight": "预检失败。",
|
|
2082
2082
|
"run": "离线执行失败。",
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* a production bundle resolves this to `false` and dead-code elimination can
|
|
6
6
|
* drop the DEV-only surfaces from the shipped UI. This is a trust boundary in
|
|
7
7
|
* the CLIENT only — the server independently refuses the Examiner API outside
|
|
8
|
-
* a dev runtime (see `
|
|
8
|
+
* a dev runtime (see `resolveLabRoot` / the offline-only gates in the examiner
|
|
9
|
+
* route).
|
|
9
10
|
*/
|
|
10
11
|
export declare const IS_DEV: boolean;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* a production bundle resolves this to `false` and dead-code elimination can
|
|
6
6
|
* drop the DEV-only surfaces from the shipped UI. This is a trust boundary in
|
|
7
7
|
* the CLIENT only — the server independently refuses the Examiner API outside
|
|
8
|
-
* a dev runtime (see `
|
|
8
|
+
* a dev runtime (see `resolveLabRoot` / the offline-only gates in the examiner
|
|
9
|
+
* route).
|
|
9
10
|
*/
|
|
10
11
|
export const IS_DEV = import.meta.env.DEV;
|