1173 lines
47 KiB
JavaScript
1173 lines
47 KiB
JavaScript
export const AUTOMATION_SUITES = Object.freeze([
|
|
{
|
|
id: 'runtime-reproducibility',
|
|
mode: 'upgrade',
|
|
// Rebuilds .runtime/portal in place. Keep this suite isolated from all
|
|
// suites that boot or inspect the shared candidate runtime.
|
|
exclusive: true,
|
|
scenarios: ['REL-03'],
|
|
cases: {
|
|
'REL-03': ['candidate plus two clean rebuilds produce the same sorted runtime tree SHA256'],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-artifact-repro.mjs'],
|
|
},
|
|
{
|
|
id: 'runtime-public-url-policy',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-05'],
|
|
cases: {
|
|
'REL-05': [
|
|
'built public HTML/CSS contains no loopback, private, or unknown TKMind public URL',
|
|
'production entry defaults the canonical H5 public base to https://m.tkmind.cn',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-public-url-scan.mjs'],
|
|
},
|
|
{
|
|
id: 'runtime-production-homolog-cold-start',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-06'],
|
|
cases: {
|
|
'REL-06': [
|
|
'packaged server cold-starts with NODE_ENV=production against unique isolated MySQL/PostgreSQL databases',
|
|
'schema initialization creates the service tables, health responds, and a second start is idempotent',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-runtime-cold-start.mjs'],
|
|
},
|
|
{
|
|
id: 'runtime-sanitized-data-upgrade',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-07'],
|
|
cases: {
|
|
'REL-07': [
|
|
'sanitized legacy MySQL user schema upgrades additively while preserving the row and password/plan defaults',
|
|
'sanitized Page Data PostgreSQL fixture remains unchanged across two packaged-runtime starts',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-runtime-upgrade.mjs'],
|
|
},
|
|
{
|
|
id: 'runtime-linux-dependency-closure',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-11'],
|
|
cases: {
|
|
'REL-11': [
|
|
'Linux ARM64 Node parses the Portal and WeChat bundles and loads the Agent Run worker',
|
|
'sandbox, MindSearch, and Excel MCP modules start in a no-network container and answer initialize',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-runtime-container.mjs'],
|
|
},
|
|
{
|
|
id: 'local-auth-full-stack',
|
|
mode: 'scenarios',
|
|
scenarios: [
|
|
'AUTH-01',
|
|
'AUTH-02',
|
|
'AUTH-03',
|
|
'AUTH-04',
|
|
'AUTH-05',
|
|
'AUTH-06',
|
|
'FILE-07',
|
|
],
|
|
cases: {
|
|
'AUTH-01': ['local-stack: login returns authenticated user, Cookie, and authenticated status'],
|
|
'AUTH-02': ['local-stack: five bad passwords return 401; next login is rate-limited with Retry-After'],
|
|
'AUTH-03': ['local-stack: a valid persisted session survives Portal restart; an invented Cookie does not'],
|
|
'AUTH-04': ['local-stack: logout revokes the old Cookie for a protected API'],
|
|
'AUTH-05': [
|
|
'local-stack: a second user cannot read the first user session, attachment, or private page',
|
|
'Page Data tests: owner mismatch, visitor roles, and own-row policies prevent private data crossover',
|
|
],
|
|
'AUTH-06': ['admin route test: an ordinary user gets 403 for reads and self-role promotion'],
|
|
'FILE-07': [
|
|
'local-stack: a second user cannot download the first user completed attachment',
|
|
'asset route tests: expired publication access and mismatched signed tokens fail closed',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-auth-scenarios.mjs'],
|
|
},
|
|
{
|
|
id: 'local-browser-smoke',
|
|
mode: 'browser',
|
|
scenarios: ['UI-01', 'UI-02', 'UI-03', 'UI-04', 'UI-05', 'UI-06', 'UI-07', 'UI-08'],
|
|
cases: {
|
|
'UI-01': ['isolated browser: desktop login reaches the authenticated app with chat and history/navigation controls'],
|
|
'UI-02': ['isolated browser: 390x844 mobile viewport exposes the stream-capable chat composer'],
|
|
'UI-03': ['isolated browser: the real application exposes attachment upload controls'],
|
|
'UI-04': ['isolated public-page replay: preview, edit, stable publish URL, and share entry work'],
|
|
'UI-05': ['isolated public-page replay: form POST returns 201 and the submitted row is rendered'],
|
|
'UI-06': ['isolated browser: login error, loading, disabled, retry/result states are visible'],
|
|
'UI-07': ['isolated browser: refresh, back/forward, and app re-entry preserve authentication and navigation state'],
|
|
'UI-08': ['isolated browser: zero console/page errors, named controls, and no horizontal mobile overflow'],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-browser-smoke.mjs'],
|
|
},
|
|
{
|
|
id: 'chat-finish-merge',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-06'],
|
|
cases: {
|
|
'CHAT-06': ['chat-finish-sync.test.mjs: Finish and UpdateConversation merge without message loss'],
|
|
},
|
|
command: [process.execPath, '--test', 'chat-finish-sync.test.mjs'],
|
|
},
|
|
{
|
|
id: 'memory-ingestion-safety',
|
|
mode: 'deterministic',
|
|
scenarios: ['MEM-13', 'MEM-14', 'MEM-15'],
|
|
cases: {
|
|
'MEM-13': [
|
|
'memory shadow matrix rejects routing prompt, Memory Context, skill, tool, system, and assistant text',
|
|
],
|
|
'MEM-14': [
|
|
'one 1000-clause evidence message produces at most one candidate and the pending pool stays bounded',
|
|
],
|
|
'MEM-15': [
|
|
'exact and semantic preference repeats deduplicate to one candidate with source ID and evidence hash',
|
|
],
|
|
},
|
|
command: [process.execPath, '--test', 'memory-v2-personal-shadow.test.mjs'],
|
|
},
|
|
{
|
|
id: 'page-public-materialization',
|
|
mode: 'deterministic',
|
|
scenarios: ['PAGE-08'],
|
|
cases: {
|
|
'PAGE-08': ['mindspace-public-finish-sync.test.mjs: chained edit_file patches materialize to public HTML'],
|
|
},
|
|
command: [process.execPath, '--test', 'mindspace-public-finish-sync.test.mjs'],
|
|
},
|
|
{
|
|
id: 'page-content-delivery-scenarios',
|
|
mode: 'scenarios',
|
|
scenarios: ['PAGE-01', 'PAGE-02'],
|
|
cases: {
|
|
'PAGE-01': [
|
|
'local scenario: a plain-text Suzhou request creates a new public HTML page, returns a MindSpace link, and responds HTTP 200 with the requested content',
|
|
],
|
|
'PAGE-02': [
|
|
'local scenario: structured long-form source content becomes a new mobile-readable public page retaining its sections, keywords, shareable link, and HTTP 200 delivery',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-page-scenarios.mjs'],
|
|
},
|
|
{
|
|
id: 'page-data-access-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['DATA-06', 'DATA-07', 'DATA-09', 'DATA-10'],
|
|
cases: {
|
|
'DATA-06': ['page-data acceptance/public tests: anonymous insert is policy-gated; admin data remains protected'],
|
|
'DATA-07': ['page-data route/public tests: CRUD, validation, export, restore, and closed-dataset behavior'],
|
|
'DATA-09': [
|
|
'Page Data abuse tests: captcha is required and verified, insert rate limits fail with 429, and one idempotency key produces exactly one row under concurrent replay',
|
|
],
|
|
'DATA-10': ['page-data acceptance/routes tests: dataset registration, page policy, and workspace binding agree'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'page-data-acceptance.test.mjs',
|
|
'page-data-browser-client.test.mjs',
|
|
'page-data-captcha.test.mjs',
|
|
'page-data-public-service.test.mjs',
|
|
'page-data-routes.test.mjs',
|
|
'page-data-session-store.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'page-data-product-scenarios',
|
|
mode: 'scenarios',
|
|
scenarios: ['DATA-01', 'DATA-02', 'DATA-03', 'DATA-04'],
|
|
cases: {
|
|
'DATA-01': [
|
|
'local scenario: AI usage survey creates a fresh questionnaire and admin page, registers a dataset/policy, and returns both delivery links',
|
|
],
|
|
'DATA-02': [
|
|
'local scenario: customer ordering creates a writable storefront plus authenticated management/statistics/export page backed by Page Data',
|
|
],
|
|
'DATA-03': [
|
|
'local scenario: supplier reporting creates validated submission and management pages backed by a registered private dataset',
|
|
],
|
|
'DATA-04': [
|
|
'local scenario: TKMind feature preference survey delivers questionnaire/admin pages, Page Data policy, dataset, and two public links',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-page-data-scenarios.mjs'],
|
|
},
|
|
{
|
|
id: 'wechat-native-image-delivery',
|
|
mode: 'deterministic',
|
|
scenarios: ['WX-05'],
|
|
cases: {
|
|
'WX-05': ['wechat-media.test.mjs: generated image is converted, origin-checked, and uploaded as native media'],
|
|
},
|
|
command: [process.execPath, '--test', 'wechat-media.test.mjs'],
|
|
},
|
|
{
|
|
id: 'mindspace-page-sync',
|
|
mode: 'deterministic',
|
|
scenarios: ['DATA-11', 'MS-04'],
|
|
cases: {
|
|
'DATA-11': ['mindspace page sync tests: remote Page Data pages sync and storage misses fall back to workspace'],
|
|
'MS-04': ['mindspace page sync tests: remote sync, thumbnail generation, and workspace fallback'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-pages.test.mjs',
|
|
'mindspace-page-sync-service.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'access-policy-modes',
|
|
mode: 'deterministic',
|
|
scenarios: ['AUTH-07'],
|
|
cases: {
|
|
'AUTH-07': [
|
|
'portal access policy tests: off, per-group enforce, master enforcement, and kill switch',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'server/portal-access-policy.test.mjs',
|
|
'server/portal-api-auth-middleware.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'security-input-boundaries',
|
|
mode: 'deterministic',
|
|
scenarios: ['AUTH-08'],
|
|
cases: {
|
|
'AUTH-08': [
|
|
'asset tests: traversal filenames and script payloads are rejected',
|
|
'Page Data tests: SQL-like keys and unauthorized columns are rejected',
|
|
'content/CSP tests: unsafe scripts and browser persistence are blocked',
|
|
'admin configuration tests: provider secrets are masked',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-assets.test.mjs',
|
|
'mindspace-content-scan.test.mjs',
|
|
'mindspace-published-page-csp.test.mjs',
|
|
'page-data-acceptance.test.mjs',
|
|
'page-data-integration.test.mjs',
|
|
'memory-v2-admin-config.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'chat-routing-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-01', 'CHAT-02', 'CHAT-03'],
|
|
cases: {
|
|
'CHAT-01': ['chat router tests: ordinary greetings select Direct Chat and produce a user-facing reply'],
|
|
'CHAT-02': ['chat router tests: page, Page Data, file, and tool intents select Agent execution'],
|
|
'CHAT-03': ['chat router tests: realtime/news questions force the web capability instead of Direct Chat'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'chat-intent-router.test.mjs',
|
|
'direct-chat-service.test.mjs',
|
|
'chat-skills.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'chat-session-continuity',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-04', 'CHAT-05'],
|
|
cases: {
|
|
'CHAT-04': ['router and broker tests: continuation/confirmation retain the active Agent session'],
|
|
'CHAT-05': ['session broker tests: explicit new sessions and eligible session reuse follow ownership rules'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'chat-intent-router.test.mjs',
|
|
'session-broker.test.mjs',
|
|
'session-reconcile.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'chat-stream-resume',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-07', 'CHAT-08'],
|
|
cases: {
|
|
'CHAT-07': ['session stream tests: Portal cursor replay resumes after disconnect without gaps or duplicates'],
|
|
'CHAT-08': ['session stream tests: Portal replay IDs never become Goose Last-Event-ID values'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'session-stream.test.mjs',
|
|
'session-stream-store.test.mjs',
|
|
'agent-run-stream.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'chat-run-failure-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-10', 'CHAT-14'],
|
|
cases: {
|
|
'CHAT-10': ['Agent Run tests: idempotency, retry, cancel, timeout, and poisoned tool history recovery'],
|
|
'CHAT-14': ['conversation display/router tests: current user correction wins over hidden routing and skill text'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'agent-run-gateway.test.mjs',
|
|
'agent-run-routes.test.mjs',
|
|
'conversation-display.test.mjs',
|
|
'chat-finish-sync.test.mjs',
|
|
'message-stream.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'chat-terminal-recovery-and-persistence',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-09', 'CHAT-11', 'CHAT-13', 'CHAT-15'],
|
|
cases: {
|
|
'CHAT-09': [
|
|
'Agent wait tests: unavailable SSE and transient status errors still poll to terminal and restore final messages',
|
|
],
|
|
'CHAT-11': [
|
|
'active-run gate tests: streaming/loading/connecting/waiting submissions are blocked before request creation',
|
|
'Agent Run route tests: active conflicts and stale recovery return bounded user-facing outcomes',
|
|
],
|
|
'CHAT-13': [
|
|
'Agent Run tests: final snapshot refresh, normalized transcript persistence, and exact row count precede success',
|
|
],
|
|
'CHAT-15': [
|
|
'canonical transcript tests: single-character visible user text is persisted in order and incomplete snapshots fail closed',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'agent-run-wait.test.mjs',
|
|
'chat-agent-run-gate.test.mjs',
|
|
'agent-run-gateway.test.mjs',
|
|
'agent-run-routes.test.mjs',
|
|
'conversation-transcript-persist.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'legacy-chat-message-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['CHAT-12'],
|
|
cases: {
|
|
'CHAT-12': [
|
|
'goose message tests: missing legacy userVisible/agentVisible and optional metadata are normalized',
|
|
'session wait tests: non-UUID request IDs remain scoped through Message and Finish',
|
|
'conversation repair tests: damaged/placeholder history restores visible legacy messages',
|
|
'Agent/WeChat recovery tests: malformed tool history is repaired without exposing the raw failure',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'goose-message.test.mjs',
|
|
'session-reply-wait.test.mjs',
|
|
'conversation-repair.test.mjs',
|
|
'conversation-transcript-persist.test.mjs',
|
|
'wechat-mp.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'memory-save-recall-lifecycle',
|
|
mode: 'deterministic',
|
|
scenarios: [
|
|
'MEM-01',
|
|
'MEM-02',
|
|
'MEM-03',
|
|
'MEM-04',
|
|
'MEM-05',
|
|
'MEM-06',
|
|
'MEM-07',
|
|
'MEM-08',
|
|
'MEM-09',
|
|
'MEM-10',
|
|
'MEM-11',
|
|
'MEM-12',
|
|
'MEM-16',
|
|
],
|
|
cases: {
|
|
'MEM-01': ['personal memory tests: explicit remember requests auto-accept and persist evidence-backed memory'],
|
|
'MEM-02': ['user memory profile tests: stored memories are injected into a newly built session context'],
|
|
'MEM-03': ['pgvector tests: semantic/hybrid retrieval recalls a paraphrased Chinese memory'],
|
|
'MEM-04': ['episodic tests: historical conversation topic is resolved with same-user evidence'],
|
|
'MEM-05': [
|
|
'conversation memory tests: a replacement preference archives the conflicting old value before recall',
|
|
'suppression tests: archived preference text is blocked from legacy and semantic fallback injection',
|
|
],
|
|
'MEM-06': ['lifecycle tests: user-scoped forget removes only the selected memory'],
|
|
'MEM-07': ['episodic tests: ordinary unrelated chat does not trigger episodic retrieval'],
|
|
'MEM-08': ['episodic/lifecycle tests: every resolve, list, and forget operation is user scoped'],
|
|
'MEM-09': ['personal memory policy tests: sensitive candidates are rejected and deletions are user scoped'],
|
|
'MEM-10': ['candidate/lifecycle tests: confirmation, promotion, expiry, and rollout scope are enforced'],
|
|
'MEM-11': ['Memory V2 runtime tests: unavailable semantic providers fall back to legacy memory'],
|
|
'MEM-12': ['memory context tests: snapshot and router payloads are bounded with evidence/source retained'],
|
|
'MEM-16': [
|
|
'deletion suppression tests: durable user tombstones block legacy, candidate, context, episodic index, and snapshot fallback re-ingestion',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'conversation-memory.test.mjs',
|
|
'user-memory-profile.test.mjs',
|
|
'episodic-memory.test.mjs',
|
|
'memory-v2.test.mjs',
|
|
'memory-v2-runtime.test.mjs',
|
|
'memory-v2-pgvector.test.mjs',
|
|
'memory-v2-lifecycle.test.mjs',
|
|
'memory-v2-personal-store.test.mjs',
|
|
'memory-v2-personal-shadow.test.mjs',
|
|
'memory-v2-suppression.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'file-rejection-and-delivery',
|
|
mode: 'deterministic',
|
|
scenarios: ['FILE-06'],
|
|
cases: {
|
|
'FILE-06': ['asset tests: traversal, script payload, MIME, size, and unsupported file rules fail closed'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-assets.test.mjs',
|
|
'mindspace-public-asset-token.test.mjs',
|
|
'mindspace-html-download-links.test.mjs',
|
|
'mindspace-chat-docx-package.test.mjs',
|
|
'wechat-media.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'file-upload-selection-and-extraction',
|
|
mode: 'deterministic',
|
|
scenarios: ['FILE-01', 'FILE-02', 'FILE-03', 'FILE-04', 'FILE-05'],
|
|
cases: {
|
|
'FILE-01': [
|
|
'asset tests: image upload is scanned, normalized, previewed, session-associated, and read by vision in order',
|
|
],
|
|
'FILE-02': [
|
|
'asset/Excel tests: an XLSX is uploaded, materialized, selected, parsed, and routed to the dedicated analyzer',
|
|
],
|
|
'FILE-03': [
|
|
'attachment tests: UTF-8 BOM and GB18030 CSV preserve Chinese fields, quoted delimiters, and empty values',
|
|
],
|
|
'FILE-04': [
|
|
'attachment tests: PDF and DOCX text plus filename/MIME metadata are extracted and previewed',
|
|
],
|
|
'FILE-05': [
|
|
'attachment tests: current-turn multiple-file order is stable, cancelled selections are excluded, and reused files do not leak prior turn state',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-assets.test.mjs',
|
|
'mindspace-asset-preview.test.mjs',
|
|
'mindspace-asset-agent.test.mjs',
|
|
'mindspace-chat-context.test.mjs',
|
|
'mindspace-attachment-text.test.mjs',
|
|
'tkmind-proxy-attachment.test.mjs',
|
|
'tkmind-proxy-vision.test.mjs',
|
|
'excel-analyst.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'excel-analysis-verified-report',
|
|
mode: 'deterministic',
|
|
scenarios: ['XLS-01', 'XLS-02', 'XLS-03', 'XLS-04', 'XLS-05', 'XLS-07', 'XLS-10'],
|
|
cases: {
|
|
'XLS-01': ['Excel engine test: a single sheet yields grouped metrics, chart, and accessible HTML report'],
|
|
'XLS-02': ['Excel engine test: sales and master-data sheets join to fixture-defined results'],
|
|
'XLS-03': ['Excel engine test: formulas, dates, totals, profit, and margin equal fixture answers'],
|
|
'XLS-04': ['Excel engine test: merged headers, blank rows, hidden sheets, and incomplete master data are bounded'],
|
|
'XLS-05': ['Excel engine test: every report KPI/chart is generated from the source workbook model and validated'],
|
|
'XLS-07': [
|
|
'Excel engine test: XLSX succeeds while XLS and CSV fail with the explicit Phase 1 supported-format contract',
|
|
],
|
|
'XLS-10': [
|
|
'Excel engine test: source workbooks remain private and absolute, traversal, symlink, and cross-user paths fail closed',
|
|
],
|
|
},
|
|
command: [process.execPath, '--test', 'excel-analyst.test.mjs'],
|
|
},
|
|
{
|
|
id: 'page-image-policy-and-repair',
|
|
mode: 'deterministic',
|
|
scenarios: ['PAGE-03', 'PAGE-04', 'PAGE-05', 'PAGE-06', 'PAGE-07', 'PAGE-13'],
|
|
cases: {
|
|
'PAGE-03': ['image policy tests: visual page intent independently decides body image generation'],
|
|
'PAGE-04': ['image generation tests: required image output is reviewed and stored before success'],
|
|
'PAGE-05': ['image policy tests: explicit no-image request disables body image generation'],
|
|
'PAGE-06': ['image generation tests: provider/review failure returns explicit failure and stores no stale image'],
|
|
'PAGE-07': ['image generation tests: purpose/idempotency keys reuse only the permitted hero/cover asset'],
|
|
'PAGE-13': [
|
|
'router test: standalone image intent selects image-generation and explicitly forbids HTML/H5/page creation',
|
|
'image service test: a replacement request uses a new current-request idempotency key, job, asset, and bitmap path',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-image-generation.test.mjs',
|
|
'mindspace-image-review.test.mjs',
|
|
'image-make-client.test.mjs',
|
|
'image-make-admin-config.test.mjs',
|
|
'wechat/image-generation-policy.test.mjs',
|
|
'mindspace-h5-html-finish-guard.test.mjs',
|
|
'chat-intent-router.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'page-scope-and-public-link-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['PAGE-09', 'PAGE-10'],
|
|
cases: {
|
|
'PAGE-09': ['public HTML scope tests: a multi-page run updates only paths touched by the current request'],
|
|
'PAGE-10': ['canonical/CSP/public link tests: filename conflicts and domain/link normalization remain valid'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-run-public-html-scope.test.mjs',
|
|
'mindspace-canonical-url.test.mjs',
|
|
'mindspace-published-page-csp.test.mjs',
|
|
'mindspace-public-links.test.mjs',
|
|
'mindspace-public-route.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'page-bounded-delivery-repair',
|
|
mode: 'deterministic',
|
|
scenarios: ['PAGE-12'],
|
|
cases: {
|
|
'PAGE-12': [
|
|
'H5 finish guard tests: incomplete public HTML/assets trigger exactly one repair and a second incomplete Finish reaches the limit',
|
|
'Agent Run tests: missing current public HTML or Page Data deliverables produce a failed terminal state',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-h5-html-finish-guard.test.mjs',
|
|
'agent-run-gateway.test.mjs',
|
|
'agent-run-deliverable-check.test.mjs',
|
|
'server/portal-session-routes.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'page-data-policy-hardening',
|
|
mode: 'deterministic',
|
|
scenarios: ['DATA-08', 'DATA-12'],
|
|
cases: {
|
|
'DATA-08': ['Page Data policy tests: updateRow/deleteRow HTML usage derives matching authenticated permissions'],
|
|
'DATA-12': ['Page Data integration tests: cross-user, SQL-like fields, unauthorized columns, and audit logs'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'page-data-policy-index.test.mjs',
|
|
'page-data-browser-client.test.mjs',
|
|
'page-data-integration.test.mjs',
|
|
'page-data-ops.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'search-provider-boundaries',
|
|
mode: 'deterministic',
|
|
scenarios: [
|
|
'SEARCH-01',
|
|
'SEARCH-02',
|
|
'SEARCH-03',
|
|
'SEARCH-04',
|
|
'SEARCH-05',
|
|
'SEARCH-06',
|
|
'SEARCH-07',
|
|
'SEARCH-08',
|
|
],
|
|
cases: {
|
|
'SEARCH-01': [
|
|
'Deep Search research test: the search provider is called across multiple rounds and the completed report retains numbered, canonical, verifiable sources',
|
|
],
|
|
'SEARCH-02': ['Deep Search tests: SearXNG results are queried, normalized, and bounded'],
|
|
'SEARCH-03': ['Deep Search tests: Reader extracts public HTML and rejects private/failed destinations'],
|
|
'SEARCH-04': ['MindSearch tests: GitHub search is capability/config gated and token-isolated'],
|
|
'SEARCH-05': [
|
|
'Deep Search LLM test: the selected provider/model drives planning and citation-safe synthesis through the authenticated Portal gateway without exposing provider secrets',
|
|
],
|
|
'SEARCH-06': [
|
|
'Deep Search HTTP test: health remains public, but a mismatched service secret returns explicit 401 UNAUTHORIZED and cannot start research',
|
|
],
|
|
'SEARCH-07': ['Deep Search tests: provider cancellation and failure handling are bounded'],
|
|
'SEARCH-08': ['capability tests: loopback search endpoints are rewritten for container host gateway access'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'deep-search.test.mjs',
|
|
'mindsearch.test.mjs',
|
|
'capabilities.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'agent-worker-safety',
|
|
mode: 'deterministic',
|
|
scenarios: [
|
|
'AGENT-01',
|
|
'AGENT-02',
|
|
'AGENT-03',
|
|
'AGENT-04',
|
|
'AGENT-05',
|
|
'AGENT-06',
|
|
'AGENT-07',
|
|
'AGENT-08',
|
|
'AGENT-09',
|
|
],
|
|
cases: {
|
|
'AGENT-01': ['Agent Run tests: an ordinary run starts a goosed session and reaches succeeded'],
|
|
'AGENT-02': ['Agent Run tests: queue concurrency and session affinity are enforced'],
|
|
'AGENT-03': [
|
|
'worker identity tests: Portal requirements and claimed worker runtime root/build ID normalize and match',
|
|
],
|
|
'AGENT-04': ['worker identity tests: required identity mismatch fails closed'],
|
|
'AGENT-05': ['Agent Run/Executor tests: request idempotency, retries, and duplicate claims are fenced'],
|
|
'AGENT-06': ['worker protocol tests: expired leases and stale runs recover or reach one terminal failure'],
|
|
'AGENT-07': ['Agent Run tests: allowlisted Aider users can execute validated code tasks'],
|
|
'AGENT-08': ['Agent Run tests: unapproved users and task types are rejected before run creation'],
|
|
'AGENT-09': ['tool/executor tests: artifact paths and workspace aliases cannot escape the user workspace'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'agent-run-gateway.test.mjs',
|
|
'agent-run-routes.test.mjs',
|
|
'agent-run-deliverable-check.test.mjs',
|
|
'tool-gateway.test.mjs',
|
|
'services/orchestrator/executor-worker-protocol.test.mjs',
|
|
'services/orchestrator/executor-worker-runtime.test.mjs',
|
|
'services/orchestrator/executor-admission-policy.test.mjs',
|
|
'services/orchestrator/executor-adapters.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'agent-extension-compatibility',
|
|
mode: 'deterministic',
|
|
scenarios: ['AGENT-10'],
|
|
cases: {
|
|
'AGENT-10': [
|
|
'capability tests: MySQL/PostgreSQL endpoints and bundled MCP module paths resolve for the target runtime',
|
|
'PostgreSQL tests: SQLite schema conversion and SET-capable tenant roles are reconciled before access',
|
|
'extension fallback test: private-data configuration failure disables only Page Data tools while non-data sandbox tools remain available',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'capabilities.test.mjs',
|
|
'mindspace-userdata-postgres.test.mjs',
|
|
'postgres-user-data-space-service.test.mjs',
|
|
'mindspace-sandbox-mcp.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'agent-exactly-once-terminal-recovery',
|
|
mode: 'deterministic',
|
|
scenarios: ['AGENT-11'],
|
|
cases: {
|
|
'AGENT-11': [
|
|
'Agent Run tests: timeout and retry exhaustion each append exactly one terminal event',
|
|
'stale heartbeat/worker recovery is fenced and a second recovery cannot create another terminal result',
|
|
'deliverable-based recovery preserves one user-visible artifact and synchronizes it once',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'agent-run-gateway.test.mjs',
|
|
'agent-run-deliverable-check.test.mjs',
|
|
'services/orchestrator/executor-worker-protocol.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'schedule-time-and-delivery',
|
|
mode: 'deterministic',
|
|
scenarios: ['SCHED-01', 'SCHED-02', 'SCHED-03', 'SCHED-04', 'SCHED-05'],
|
|
cases: {
|
|
'SCHED-01': ['schedule service tests: wall-clock input resolves in the configured user timezone'],
|
|
'SCHED-02': ['schedule intent tests: missing or ambiguous times require clarification'],
|
|
'SCHED-03': ['schedule service tests: cancel and bulk delete update only the user reminder'],
|
|
'SCHED-04': [
|
|
'worker tests: a failed delivery retries, reaches one success, and cannot send again after sent state',
|
|
],
|
|
'SCHED-05': [
|
|
'worker restart test: shared persisted pending state survives process replacement and sends once',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'schedule-intent.test.mjs',
|
|
'schedule-service.test.mjs',
|
|
'schedule-reminder-worker.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'wechat-channel-contract',
|
|
mode: 'deterministic',
|
|
scenarios: [
|
|
'WX-01',
|
|
'WX-02',
|
|
'WX-03',
|
|
'WX-04',
|
|
'WX-06',
|
|
'WX-07',
|
|
'WX-08',
|
|
'FILE-08',
|
|
],
|
|
cases: {
|
|
'WX-01': ['WeChat MP tests: plaintext/AES signatures and connectivity challenge validate'],
|
|
'WX-02': ['WeChat MP tests: duplicate message IDs are ignored'],
|
|
'WX-03': ['WeChat MP tests: openid binding and dedicated user session isolation are preserved'],
|
|
'WX-04': ['WeChat MP tests: page output resolves to the canonical public link'],
|
|
'WX-06': ['WeChat MP tests: current-run thumbnail is required and one unambiguous missing asset is repaired'],
|
|
'WX-07': ['WeChat OAuth tests: callback configuration, state, and return URL reject external redirects'],
|
|
'WX-08': ['WeChat Pay tests: sandbox callback signature and message/channel boundaries validate'],
|
|
'FILE-08': [
|
|
'DOCX package tests: generated bytes are persisted, registered in the manifest, and exposed only through the canonical artifact download URL',
|
|
'download-link and asset-route tests: page buttons resolve to an existing sibling or asset API; authenticated, signed-public, expired, and denied access paths are enforced',
|
|
'WeChat tests: Word/Excel media is persisted into the user public area with H5 attachment metadata, and Word page tasks require the real DOCX artifact before HTML delivery',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'wechat-mp.test.mjs',
|
|
'wechat-oauth.test.mjs',
|
|
'wechat-pay.test.mjs',
|
|
'wechat-media.test.mjs',
|
|
'wechat/wechat-channel.test.mjs',
|
|
'wechat/image-generation-policy.test.mjs',
|
|
'mindspace-chat-docx-package.test.mjs',
|
|
'mindspace-html-download-links.test.mjs',
|
|
'mindspace-public-asset-token.test.mjs',
|
|
'server/portal-mindspace-asset-routes.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'wechat-terminal-and-atomic-delivery',
|
|
mode: 'deterministic',
|
|
scenarios: ['WX-09', 'WX-10', 'WX-11', 'WX-12', 'WX-13'],
|
|
cases: {
|
|
'WX-09': [
|
|
'WeChat ledger tests: duplicates stay fenced, stale processing is reclaimed, and accepted work reaches done or failed',
|
|
],
|
|
'WX-10': [
|
|
'image turn tests: historical image_url content is scrubbed before text follow-up and an unsupported update rotates the session',
|
|
],
|
|
'WX-11': [
|
|
'WeChat delivery tests: 45047/45015 persist one deferred result and claim it once on the next passive response',
|
|
],
|
|
'WX-12': [
|
|
'voice tests: AMR media reaches ASR and conversion/recognition failures return an explicit retry message without Agent execution',
|
|
],
|
|
'WX-13': [
|
|
'page delivery tests: real HTML, fresh current-run raster cover, description, platform brand, and verified public URL are required before send',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'user-auth.test.mjs',
|
|
'wechat-mp.test.mjs',
|
|
'wechat-media.test.mjs',
|
|
'wechat/wechat-channel.test.mjs',
|
|
'chat-image-turn-scope.test.mjs',
|
|
'tkmind-proxy.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'billing-plan-and-idempotency',
|
|
mode: 'deterministic',
|
|
scenarios: ['BILL-01', 'BILL-04', 'BILL-05'],
|
|
cases: {
|
|
'BILL-01': ['subscription tests: free, paid, unlimited, and administrator entitlements are calculated'],
|
|
'BILL-04': ['billing concurrency tests: Finish/SSE replay with the same request is charged once'],
|
|
'BILL-05': ['billing concurrency tests: concurrent Finish settlement atomically deducts one charge'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'billing.test.mjs',
|
|
'billing-token-state.test.mjs',
|
|
'billing-subscription.test.mjs',
|
|
'billing-session-concurrency.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'billing-execution-terminal-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['BILL-02', 'BILL-03'],
|
|
cases: {
|
|
'BILL-02': [
|
|
'Direct Chat and Agent Finish tests: each successful execution enters settlement once with the stable request ID',
|
|
'billing state tests: repeated and concurrent settlement attempts charge once',
|
|
],
|
|
'BILL-03': [
|
|
'Direct/Agent tests: provider failure, cancellation, and a truly hanging SSE timeout never enter billing',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'direct-chat-service.test.mjs',
|
|
'tkmind-proxy.test.mjs',
|
|
'session-reply-wait.test.mjs',
|
|
'billing-session-concurrency.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'billing-recharge-and-admission-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['BILL-06', 'BILL-07'],
|
|
cases: {
|
|
'BILL-06': [
|
|
'recharge service tests: forged WeChat callback signatures fail before credit, and a signed callback plus replay credits exactly once',
|
|
],
|
|
'BILL-07': [
|
|
'Portal Agent route test: an insufficient-balance response returns 402 before the run handler and leaves no residual task',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'billing-recharge.test.mjs',
|
|
'wechat-pay.test.mjs',
|
|
'server/portal-webhook-routes.test.mjs',
|
|
'server/portal-agent-runtime-routes.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'mindspace-delivery-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['MS-01', 'MS-02', 'MS-03', 'MS-05', 'MS-06', 'MS-07', 'MS-08'],
|
|
cases: {
|
|
'MS-01': ['MindSpace service tests: health and versioned contract endpoints respond with the contract'],
|
|
'MS-02': ['MindSpace adapter tests: local and remote adapters satisfy the same server contract'],
|
|
'MS-03': ['public delivery tests: canonical, OG, sharing, and access behavior are stable'],
|
|
'MS-05': ['conversation package tests: create, verify, registry, and historical backfill are consistent'],
|
|
'MS-06': ['publication/download tests: DOCX and long-image companions exist and use non-local canonical links'],
|
|
'MS-07': ['content/CSP tests: scan and localization reject dangerous scripts while retaining safe pages'],
|
|
'MS-08': ['cleanup/purge tests: page and conversation deletion removes linked resources without orphans'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'mindspace-service/mindspace-rpc-server.test.mjs',
|
|
'mindspace-local-server-adapter.test.mjs',
|
|
'mindspace-remote-server-adapter.test.mjs',
|
|
'mindspace-server-adapter.test.mjs',
|
|
'mindspace-public-delivery.test.mjs',
|
|
'mindspace-publications.test.mjs',
|
|
'mindspace-conversation-package.test.mjs',
|
|
'mindspace-conversation-package-backfill.test.mjs',
|
|
'mindspace-conversation-package-verify.test.mjs',
|
|
'mindspace-html-download-links.test.mjs',
|
|
'mindspace-content-scan.test.mjs',
|
|
'mindspace-published-page-csp.test.mjs',
|
|
'mindspace-cleanup.test.mjs',
|
|
'mindspace-page-purge.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'plaza-publication-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['PLAZA-01', 'PLAZA-02', 'PLAZA-03', 'PLAZA-04', 'PLAZA-05'],
|
|
cases: {
|
|
'PLAZA-01': ['Plaza integration tests: publish, moderate, and feed visibility preserve page content/link'],
|
|
'PLAZA-02': ['Plaza post/SEO tests: discovery, search metadata, cover, and public URL normalize'],
|
|
'PLAZA-03': ['Plaza interaction tests: reaction types and moderation/role permissions are enforced'],
|
|
'PLAZA-04': ['Plaza algorithm tests: fixed fixtures yield stable hot score, MMR, cursor, and cold start order'],
|
|
'PLAZA-05': [
|
|
'Plaza public/feed/recommendation tests: hidden posts and offline, private, or deleted source pages are inaccessible and invalidate stale feed caches',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'plaza-integration.test.mjs',
|
|
'plaza-posts.test.mjs',
|
|
'plaza-interactions.test.mjs',
|
|
'plaza-ops.test.mjs',
|
|
'plaza-seo.test.mjs',
|
|
'plaza-algorithm.test.mjs',
|
|
'plaza-recommend.test.mjs',
|
|
'plaza-public.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'configuration-observability-contract',
|
|
mode: 'deterministic',
|
|
scenarios: ['CFG-01', 'CFG-02', 'CFG-03', 'CFG-04', 'CFG-05', 'CFG-06', 'CFG-07'],
|
|
cases: {
|
|
'CFG-01': ['Orchestrator config/bootstrap tests: disabled mode is not a Portal startup/request dependency'],
|
|
'CFG-02': ['shadow dispatcher/observer tests: Shadow failures never change the Native user result'],
|
|
'CFG-03': ['Orchestrator/access policy tests: emergency kill switches stop controlled execution immediately'],
|
|
'CFG-04': ['analytics tests: disabled mode emits nothing; enabled events use bounded pseudonymous context'],
|
|
'CFG-05': ['system disclosure tests: shadow records only, enforce refuses before execution'],
|
|
'CFG-06': ['configuration migration tests: env-to-database setup is versioned and idempotent'],
|
|
'CFG-07': ['observability tests: logs, metrics, and audit are traceable and exclude raw identity/secrets'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'services/orchestrator/admin-config.test.mjs',
|
|
'services/orchestrator/shadow-dispatcher.test.mjs',
|
|
'services/orchestrator/shadow-observer.test.mjs',
|
|
'services/orchestrator/observability.test.mjs',
|
|
'mindspace-analytics.test.mjs',
|
|
'mindspace-rybbit.test.mjs',
|
|
'system-disclosure-policy.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'provider-model-catalog-compatibility',
|
|
mode: 'deterministic',
|
|
scenarios: ['CFG-08'],
|
|
cases: {
|
|
'CFG-08': [
|
|
'Provider tests: every model stored in an active custom database profile is accepted',
|
|
'Provider tests: a builtin legacy model removed from the current catalog is rejected before selection or sync',
|
|
],
|
|
},
|
|
command: [process.execPath, '--test', 'llm-providers.test.mjs'],
|
|
},
|
|
{
|
|
id: 'release-goosed-runtime-identity',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-08'],
|
|
cases: {
|
|
'REL-08': [
|
|
'release contract: exactly nine goosed containers are recreated after live swap, then ports, health, MCP paths, runtime identity, Portal, worker, and tunnel are checked',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/check-release-runtime-safety.mjs', 'REL-08'],
|
|
},
|
|
{
|
|
id: 'release-rollback-restoration',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-09'],
|
|
cases: {
|
|
'REL-09': [
|
|
'release contract: post-swap failure must archive the failed new live, restore old live, and restart the previous Portal',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/check-release-runtime-safety.mjs', 'REL-09'],
|
|
},
|
|
{
|
|
id: 'release-drain-backup-and-pre-swap-safety',
|
|
mode: 'upgrade',
|
|
scenarios: ['REL-10'],
|
|
cases: {
|
|
'REL-10': [
|
|
'release contract: block new Agent runs, drain active work within a bound, checksum and back up, then recheck zero active runs immediately before swap',
|
|
'canary contract: immutable user and WeChat identities route to an isolated candidate, while missing identity, resolver errors, and candidate failure fall back to stable',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'release-gate/canary-routing.test.mjs',
|
|
'memind-canary-proxy.test.mjs',
|
|
'release-gate/release-runtime-safety.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'image-to-page-recorded-replay',
|
|
mode: 'deterministic',
|
|
scenarios: [
|
|
'IMGPG-01',
|
|
'IMGPG-02',
|
|
'IMGPG-03',
|
|
'IMGPG-04',
|
|
'IMGPG-05',
|
|
'IMGPG-06',
|
|
'IMGPG-07',
|
|
'IMGPG-08',
|
|
'PAGE-11',
|
|
],
|
|
cases: {
|
|
'IMGPG-01': ['recorded vision/tool replay materializes a responsive single-image-capable HTML page'],
|
|
'IMGPG-02': ['recorded Qwen vision/OCR result is retained in the structurally valid page artifact'],
|
|
'IMGPG-03': ['two current-turn image inputs and generated figure references preserve user order'],
|
|
'IMGPG-04': ['recorded image facts plus text requirements jointly determine copy, color, and responsive layout'],
|
|
'IMGPG-05': ['artifact uses relative uploaded image paths and rejects host filesystem, loopback, and temporary URLs'],
|
|
'IMGPG-06': ['delivery injects OG/share metadata with the public image and stable canonical page URL'],
|
|
'IMGPG-07': ['edit_file replay changes copy in place while preserving page path and original image references'],
|
|
'IMGPG-08': ['403/unreadable image cannot call vision, bill usage, or invent recognition text'],
|
|
'PAGE-11': ['daily page fixture requires news, weather, market, knowledge, authoritative HTTPS citations, compliance notice, viewport, and HTML artifact'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'release-gate/image-page-replay.test.mjs',
|
|
'mindspace-thumbnails.test.mjs',
|
|
'mindspace-og-tags.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'excel-continuity-and-fallback',
|
|
mode: 'deterministic',
|
|
scenarios: ['XLS-06', 'XLS-08', 'XLS-09', 'XLS-11', 'XLS-12'],
|
|
cases: {
|
|
'XLS-06': ['file, scan-cell, sample-row, and memory-facing ZIP budgets reject oversized input before unbounded work'],
|
|
'XLS-08': ['a follow-up changes group dimension while reusing the exact same uploaded workbook path'],
|
|
'XLS-09': ['report names the source workbook and renders a validated asset download URL'],
|
|
'XLS-11': ['an approximately 5MB multi-sheet input crosses a bounded tool budget; fallback contains only preverified totals and a real artifact'],
|
|
'XLS-12': ['updated workbook regenerates the same dashboard path while retaining old rows, confirmed title, and dimensions'],
|
|
},
|
|
command: [process.execPath, '--test', 'release-gate/excel-continuity.test.mjs'],
|
|
},
|
|
{
|
|
id: 'page-data-schema-evolution',
|
|
mode: 'deterministic',
|
|
scenarios: ['DATA-05', 'DATA-13'],
|
|
cases: {
|
|
'DATA-05': ['children survey adds diet additively; historical hobby row remains and new diet row is writable'],
|
|
'DATA-13': [
|
|
'incomplete/readonly dataset fails closed, then additive fields and actions rebind without losing the historical row or duplicating created_at',
|
|
'legacy API and browser storage are rejected; soft-delete policy is derived only after matching schema registration',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'release-gate/page-data-evolution.test.mjs',
|
|
'mindspace-page-data-finish-guard.test.mjs',
|
|
'page-data-workspace-bind.test.mjs',
|
|
'mindspace-pages.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'offline-document-native-delivery',
|
|
mode: 'deterministic',
|
|
scenarios: ['MS-09'],
|
|
cases: {
|
|
'MS-09': [
|
|
'stdlib DOCX generator has no network/font dependency, produces a real ZIP/DOCX, is synced beside HTML, and uses verified direct/native download paths',
|
|
],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'release-gate/document-offline.test.mjs',
|
|
'mindspace-sandbox-mcp.test.mjs',
|
|
'mindspace-public-finish-sync.test.mjs',
|
|
'mindspace-html-download-links.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'legacy-data-compatibility',
|
|
mode: 'deterministic',
|
|
scenarios: ['COMP-01', 'COMP-02', 'COMP-03', 'COMP-04'],
|
|
cases: {
|
|
'COMP-01': ['legacy/non-UUID messages and prior direct-session transcript survive normalization and continue in a Goose session'],
|
|
'COMP-02': ['legacy public routes, browser-storage pages, missing storage objects, and existing page identity remain readable after sync'],
|
|
'COMP-03': ['existing Page Data rows, registry, policy, public form, export, soft delete, and restore remain usable'],
|
|
'COMP-04': ['legacy memory remains recallable through Memory V2 and safely falls back when semantic storage is unavailable'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'conversation-transcript-persist.test.mjs',
|
|
'goose-message.test.mjs',
|
|
'mindspace-public-route.test.mjs',
|
|
'mindspace-pages.test.mjs',
|
|
'mindspace-page-sync.test.mjs',
|
|
'page-data-integration.test.mjs',
|
|
'memory-v2.test.mjs',
|
|
'episodic-memory.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'fault-isolation-and-concurrency',
|
|
mode: 'deterministic',
|
|
scenarios: ['COMP-05', 'COMP-06', 'COMP-07', 'COMP-08'],
|
|
cases: {
|
|
'COMP-05': ['worker protocol fences one failed/expired worker lease and recovers the run exactly once'],
|
|
'COMP-06': ['temporary status/database failures retry or recover to one consistent terminal state'],
|
|
'COMP-07': ['image, search, and semantic-memory provider failures are bounded and do not break core direct chat'],
|
|
'COMP-08': ['concurrent billing, session allocation, file parsing, and page generation tests enforce bounded completion and no duplicate terminal/resource state'],
|
|
},
|
|
command: [
|
|
process.execPath,
|
|
'--test',
|
|
'services/orchestrator/executor-worker-protocol.test.mjs',
|
|
'agent-run-wait.test.mjs',
|
|
'agent-run-gateway.test.mjs',
|
|
'direct-chat-service.test.mjs',
|
|
'mindspace-image-generation.test.mjs',
|
|
'deep-search.test.mjs',
|
|
'memory-v2-runtime.test.mjs',
|
|
'billing-session-concurrency.test.mjs',
|
|
'session-broker.test.mjs',
|
|
],
|
|
},
|
|
{
|
|
id: 'sanitized-production-regression-replay',
|
|
mode: 'upgrade',
|
|
scenarios: ['COMP-09'],
|
|
cases: {
|
|
'COMP-09': [
|
|
'every active privacy-reviewed production regression fixture executes in the isolated runner; production addresses/credentials are refused in code',
|
|
],
|
|
},
|
|
command: [process.execPath, 'scripts/run-release-gate-regression-corpus.mjs'],
|
|
},
|
|
]);
|
|
|
|
export function validateAutomationSuites(catalog) {
|
|
const catalogIds = new Set(catalog.map((scenario) => scenario.id));
|
|
const seen = new Set();
|
|
for (const suite of AUTOMATION_SUITES) {
|
|
if (
|
|
!suite.id
|
|
|| !suite.mode
|
|
|| !Array.isArray(suite.command)
|
|
|| suite.command.length < 2
|
|
|| !suite.cases
|
|
|| typeof suite.cases !== 'object'
|
|
) {
|
|
throw new Error(`Invalid automation suite: ${suite.id ?? '<missing>'}`);
|
|
}
|
|
for (const scenarioId of suite.scenarios) {
|
|
if (!catalogIds.has(scenarioId)) {
|
|
throw new Error(`Automation suite ${suite.id} references unknown scenario ${scenarioId}`);
|
|
}
|
|
if (seen.has(scenarioId)) {
|
|
throw new Error(`Scenario ${scenarioId} is assigned to multiple automation suites`);
|
|
}
|
|
if (!Array.isArray(suite.cases[scenarioId]) || suite.cases[scenarioId].length === 0) {
|
|
throw new Error(`Automation suite ${suite.id} has no asserted cases for ${scenarioId}`);
|
|
}
|
|
if (suite.cases[scenarioId].some((item) => typeof item !== 'string' || item.trim() === '')) {
|
|
throw new Error(`Automation suite ${suite.id} has an invalid asserted case for ${scenarioId}`);
|
|
}
|
|
seen.add(scenarioId);
|
|
}
|
|
const extraCases = Object.keys(suite.cases).filter((scenarioId) => !suite.scenarios.includes(scenarioId));
|
|
if (extraCases.length > 0) {
|
|
throw new Error(`Automation suite ${suite.id} has cases for unassigned scenarios: ${extraCases.join(', ')}`);
|
|
}
|
|
}
|
|
return AUTOMATION_SUITES;
|
|
}
|