Skip to content

Commit 7572ee4

Browse files
committed
fix(testing): harden foundation runtime verification commands
1 parent da7c945 commit 7572ee4

6 files changed

Lines changed: 129 additions & 25 deletions

File tree

docs/en/task.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,18 @@
3434
3. The live query comparison, staleness, learning-quality, and session-plan-quality diagnostics are calibrated on top of a release-grade graphdb/ANN baseline.
3535
4. Tutor routing advances from local-first adapter execution into a production-proven multi-provider policy while keeping explicit fallback behavior.
3636
5. Tauri desktop + Android path remains documented, verified, and cleanly separated from historical Electron context.
37+
38+
### Core Real-Machine Test Commands
39+
40+
- `npm run verify:foundation:sqlite-runtime:matrix`
41+
- Highest-value host/runtime proof for the embedded sqlite graph backend across `smoke` / `medium` / `heavy` workloads.
42+
- `npm run verify:foundation:ann-runtime:matrix`
43+
- Highest-value host/runtime proof for the `external_http` ANN connector across `smoke` / `medium` / `heavy` workloads.
44+
- `npm run verify:agent-workspace:browser`
45+
- Real browser smoke for agent workspace, runbook cards, query/quality/session surfaces, and focus/path flows.
46+
- `npm run verify:agent-workspace:tauri`
47+
- Real desktop-shell smoke for the current Tauri app path.
48+
- `npm run tauri:dev:mini:gpu`
49+
- Primary desktop real-machine interactive command when you want to manually drive the app in the mini GPU-enabled shell.
50+
- `npm run tauri:android:dev`
51+
- Primary Android real-device interactive command when you want to push the current app to a connected device.

docs/zh/task.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@
3131
4. tutor routing 从 local-first adapter 执行推进到生产级多 provider 策略,同时保留明确的 fallback。
3232
5. Tauri 桌面与 Android 路径继续保持可验证、可文档化,并与历史 Electron 上下文清晰分层。
3333

34+
### 核心实机测试命令
35+
36+
- `npm run verify:foundation:sqlite-runtime:matrix`
37+
- 当前 embedded sqlite 图后端最有价值的主机/runtime 证明,覆盖 `smoke` / `medium` / `heavy` 三档 workload。
38+
- `npm run verify:foundation:ann-runtime:matrix`
39+
- 当前 `external_http` ANN connector 最有价值的主机/runtime 证明,覆盖 `smoke` / `medium` / `heavy` 三档 workload。
40+
- `npm run verify:agent-workspace:browser`
41+
- 真实浏览器 smoke,覆盖 agent workspace、runbook 卡片、query/quality/session 面板和 focus/path 流程。
42+
- `npm run verify:agent-workspace:tauri`
43+
- 当前 Tauri 桌面壳层路径的真实 smoke。
44+
- `npm run tauri:dev:mini:gpu`
45+
- 你要做桌面端手动实机交互测试时,优先使用的 mini GPU 壳层命令。
46+
- `npm run tauri:android:dev`
47+
- 你要把当前应用推到已连接 Android 实机上做交互测试时,优先使用的命令。
48+
3449
---
3550

3651
# Task: Refining Path Mode Visualization

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@
9292
"test:conversation-turn-cache:durability": "jest src/notemd.server.integration.test.ts --runInBand --testNamePattern=\"turn-cache alert trend restart durability\"",
9393
"test:license:contract": "jest src/license.policy.contract.test.ts --runInBand",
9494
"verify:agent-workspace:runtime": "node scripts/verify-agent-workspace-runtime.js",
95-
"verify:foundation:ann-runtime": "node scripts/verify-foundation-ann-runtime.js",
96-
"verify:foundation:ann-runtime:matrix": "node scripts/verify-foundation-ann-runtime.js --matrix",
97-
"verify:foundation:sqlite-runtime": "node scripts/verify-foundation-sqlite-runtime.js",
98-
"verify:foundation:sqlite-runtime:heavy": "node scripts/verify-foundation-sqlite-runtime.js --heavy",
99-
"verify:foundation:sqlite-runtime:matrix": "node scripts/verify-foundation-sqlite-runtime.js --matrix",
95+
"verify:foundation:ann-runtime": "npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-ann-runtime.js",
96+
"verify:foundation:ann-runtime:matrix": "npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-ann-runtime.js --matrix",
97+
"verify:foundation:sqlite-runtime": "npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-sqlite-runtime.js",
98+
"verify:foundation:sqlite-runtime:heavy": "npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-sqlite-runtime.js --heavy",
99+
"verify:foundation:sqlite-runtime:matrix": "npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-sqlite-runtime.js --matrix",
100100
"verify:agent-workspace:browser": "node scripts/verify-agent-workspace-browser.js",
101101
"verify:agent-workspace:tauri": "node scripts/verify-agent-workspace-tauri.js",
102102
"verify:agent-workspace:tauri:window-evidence": "node scripts/verify-agent-workspace-tauri-window-evidence.js",

scripts/verify-foundation-ann-runtime.js

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const DIST_FRONTEND_DIR = path.join(REPO_ROOT, 'dist', 'src', 'frontend');
1212
const LOOPBACK_HOST = '127.0.0.1';
1313
const STARTUP_TIMEOUT_MS = 30000;
1414
const SHUTDOWN_TIMEOUT_MS = 8000;
15+
const REQUEST_TIMEOUT_SCALE = Number.isFinite(Number(process.env.NOTE_CONNECTION_FOUNDATION_ANN_TIMEOUT_SCALE))
16+
? Math.max(0.5, Number(process.env.NOTE_CONNECTION_FOUNDATION_ANN_TIMEOUT_SCALE))
17+
: 1;
1518
const WORKLOAD_PROFILES = {
1619
smoke: {
1720
profileId: 'smoke',
@@ -158,7 +161,29 @@ function getFreePort() {
158161
});
159162
}
160163

161-
function requestJson(port, method, requestPath, body) {
164+
function computeRequestTimeoutMs(context = {}) {
165+
const requestPath = String(context.requestPath || '').trim();
166+
const workloadProfile = context.workloadProfile || { documentCount: 1 };
167+
const documentCount = Math.max(1, Math.floor(Number(workloadProfile.documentCount || 1)));
168+
const mode = String(context.mode || '').trim();
169+
let timeoutMs = 6000;
170+
171+
if (requestPath === '/api/knowledge/ingest') {
172+
timeoutMs = Math.max(20000, documentCount * 450);
173+
} else if (requestPath === '/api/knowledge/query') {
174+
timeoutMs = Math.max(8000, documentCount * 60);
175+
} else if (requestPath === '/api/knowledge/query-backend-diagnostics') {
176+
timeoutMs = Math.max(6000, documentCount * 30);
177+
}
178+
179+
if (mode === 'packaged_sidecar') {
180+
timeoutMs = Math.round(timeoutMs * 2);
181+
}
182+
183+
return Math.max(2000, Math.round(timeoutMs * REQUEST_TIMEOUT_SCALE));
184+
}
185+
186+
function requestJson(port, method, requestPath, body, timeoutMs = 6000) {
162187
return new Promise((resolve, reject) => {
163188
const payload = typeof body === 'undefined'
164189
? null
@@ -199,7 +224,7 @@ function requestJson(port, method, requestPath, body) {
199224
}
200225
);
201226

202-
req.setTimeout(2000, () => {
227+
req.setTimeout(timeoutMs, () => {
203228
req.destroy(new Error(`Timed out requesting ${requestPath}`));
204229
});
205230
req.once('error', reject);
@@ -354,12 +379,21 @@ async function startReferenceAnnService(port, state) {
354379
return server;
355380
}
356381

357-
async function waitForServer(port, timeoutMs) {
382+
async function waitForServer(port, timeoutMs, context = {}) {
358383
const startedAt = Date.now();
359384
let lastError = null;
360385
while ((Date.now() - startedAt) < timeoutMs) {
361386
try {
362-
const response = await requestJson(port, 'GET', '/api/knowledge/query-backend-diagnostics');
387+
const response = await requestJson(
388+
port,
389+
'GET',
390+
'/api/knowledge/query-backend-diagnostics',
391+
undefined,
392+
computeRequestTimeoutMs({
393+
...context,
394+
requestPath: '/api/knowledge/query-backend-diagnostics',
395+
})
396+
);
363397
if (response.status >= 200 && response.status < 500) {
364398
return;
365399
}
@@ -667,10 +701,20 @@ function assertAnnState(state, mode, phase, workloadProfile, minSelectCount) {
667701
};
668702
}
669703

670-
async function runQueries(port, mode, phase, workloadQueries) {
704+
async function runQueries(port, mode, phase, workloadProfile, workloadQueries) {
671705
const queryResults = [];
672706
for (const queryPlan of workloadQueries) {
673-
const queryResponse = await requestJson(port, 'POST', '/api/knowledge/query', queryPlan.request);
707+
const queryResponse = await requestJson(
708+
port,
709+
'POST',
710+
'/api/knowledge/query',
711+
queryPlan.request,
712+
computeRequestTimeoutMs({
713+
requestPath: '/api/knowledge/query',
714+
workloadProfile,
715+
mode,
716+
})
717+
);
674718
queryResults.push({
675719
phaseId: queryPlan.phaseId,
676720
...assertQueryResponse(queryResponse, mode, `${phase}:${queryPlan.phaseId}`, {
@@ -707,14 +751,34 @@ async function runScenario(mode, workloadProfile) {
707751

708752
try {
709753
runtime = spawnRuntime(mode, { port, bridgePort, connectorPort, fixture });
710-
await waitForServer(port, STARTUP_TIMEOUT_MS);
711-
712-
const ingestResponse = await requestJson(port, 'POST', '/api/knowledge/ingest', ingestPayload);
754+
await waitForServer(port, STARTUP_TIMEOUT_MS, { workloadProfile, mode });
755+
756+
const ingestResponse = await requestJson(
757+
port,
758+
'POST',
759+
'/api/knowledge/ingest',
760+
ingestPayload,
761+
computeRequestTimeoutMs({
762+
requestPath: '/api/knowledge/ingest',
763+
workloadProfile,
764+
mode,
765+
})
766+
);
713767
assertCondition(ingestResponse.status === 200, `[${mode}] ingest status=${ingestResponse.status}`);
714768
assertCondition(ingestResponse.body && ingestResponse.body.success === true, `[${mode}] ingest success!=true`);
715769

716-
const firstQueries = await runQueries(port, mode, 'first_pass', workloadQueries);
717-
const firstDiagnosticsResponse = await requestJson(port, 'GET', '/api/knowledge/query-backend-diagnostics');
770+
const firstQueries = await runQueries(port, mode, 'first_pass', workloadProfile, workloadQueries);
771+
const firstDiagnosticsResponse = await requestJson(
772+
port,
773+
'GET',
774+
'/api/knowledge/query-backend-diagnostics',
775+
undefined,
776+
computeRequestTimeoutMs({
777+
requestPath: '/api/knowledge/query-backend-diagnostics',
778+
workloadProfile,
779+
mode,
780+
})
781+
);
718782
const firstDiagnostics = assertDiagnostics(
719783
firstDiagnosticsResponse,
720784
mode,
@@ -737,10 +801,20 @@ async function runScenario(mode, workloadProfile) {
737801
port = await getFreePort();
738802
bridgePort = await getFreePort();
739803
runtime = spawnRuntime(mode, { port, bridgePort, connectorPort, fixture });
740-
await waitForServer(port, STARTUP_TIMEOUT_MS);
741-
742-
const restartQueries = await runQueries(port, mode, 'restart_pass', workloadQueries);
743-
const restartDiagnosticsResponse = await requestJson(port, 'GET', '/api/knowledge/query-backend-diagnostics');
804+
await waitForServer(port, STARTUP_TIMEOUT_MS, { workloadProfile, mode });
805+
806+
const restartQueries = await runQueries(port, mode, 'restart_pass', workloadProfile, workloadQueries);
807+
const restartDiagnosticsResponse = await requestJson(
808+
port,
809+
'GET',
810+
'/api/knowledge/query-backend-diagnostics',
811+
undefined,
812+
computeRequestTimeoutMs({
813+
requestPath: '/api/knowledge/query-backend-diagnostics',
814+
workloadProfile,
815+
mode,
816+
})
817+
);
744818
const restartDiagnostics = assertDiagnostics(
745819
restartDiagnosticsResponse,
746820
mode,

src/foundation.ann.runtime.contract.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ describe('foundation ann runtime verification contract', () => {
1818
test('keeps the host-level ann runtime verifier wired in package scripts', () => {
1919
const packageJson = readJson<PackageJson>(packageJsonPath);
2020
expect(packageJson.scripts?.['verify:foundation:ann-runtime']).toBe(
21-
'node scripts/verify-foundation-ann-runtime.js'
21+
'npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-ann-runtime.js'
2222
);
2323
expect(packageJson.scripts?.['verify:foundation:ann-runtime:matrix']).toBe(
24-
'node scripts/verify-foundation-ann-runtime.js --matrix'
24+
'npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-ann-runtime.js --matrix'
2525
);
2626
});
2727

src/foundation.sqlite.runtime.contract.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ describe('foundation sqlite runtime verification contract', () => {
1818
test('keeps the host-level sqlite runtime verifier wired in package scripts', () => {
1919
const packageJson = readJson<PackageJson>(packageJsonPath);
2020
expect(packageJson.scripts?.['verify:foundation:sqlite-runtime']).toBe(
21-
'node scripts/verify-foundation-sqlite-runtime.js'
21+
'npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-sqlite-runtime.js'
2222
);
2323
expect(packageJson.scripts?.['verify:foundation:sqlite-runtime:heavy']).toBe(
24-
'node scripts/verify-foundation-sqlite-runtime.js --heavy'
24+
'npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-sqlite-runtime.js --heavy'
2525
);
2626
expect(packageJson.scripts?.['verify:foundation:sqlite-runtime:matrix']).toBe(
27-
'node scripts/verify-foundation-sqlite-runtime.js --matrix'
27+
'npm run build && node scripts/ensure-sidecar-ready.js && node scripts/verify-foundation-sqlite-runtime.js --matrix'
2828
);
2929
});
3030

0 commit comments

Comments
 (0)