Files
memind/release-gate/coverage.mjs
T
john fde6503bdf
Memind CI / Test, build, and release guards (push) Has been cancelled
feat(mindspace): add SEO/GEO delivery, page template catalog, and admin hooks
Enable optional SEO/GEO injection and discovery routes for confirmed public pages while keeping private pages noindex. Add premium page template skills, portal catalog API, template shop UI, and Baidu push gated by memind_adm config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 08:06:12 +08:00

1181 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': ['two consecutive 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, SEO/GEO index policy, 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-index-policy.test.mjs',
'mindspace-seo-tags.test.mjs',
'mindspace-geo-tags.test.mjs',
'mindspace-seo-geo-delivery.test.mjs',
'mindspace-seo-discovery-service.test.mjs',
'mindspace-seo-notify.test.mjs',
'server/portal-seo-discovery-routes.test.mjs',
'server/portal-domain-services-bootstrap.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;
}