import assert from 'node:assert/strict';
import { execFileSync } from 'node:child_process';
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { createConsoleServer } from '../../src/console/server.mjs';
import { openControlPlane } from '../../src/control-plane/service.mjs';
import { analyzeRepository } from '../../src/kernel/analyze.mjs';
import { proposeDomains } from '../../src/kernel/domains.mjs';
import { diagnoseProject } from '../../src/kernel/doctor.mjs';
import { inspectRepository } from '../../src/kernel/git.mjs';
import { installProject } from '../../src/kernel/install.mjs';
import { organizationGraphFromConfig } from '../../src/kernel/organization.mjs';
import { createWorktrees } from '../../src/kernel/worktrees.mjs';
import { observeProject } from '../../src/observability/snapshot.mjs';
function fixture() {
const root = mkdtempSync(join(tmpdir(), 'torch-console-'));
execFileSync('git', ['init', '-b', 'main', root]);
execFileSync('git', ['-C', root, 'config', 'user.email', 'torch-test@example.invalid']);
execFileSync('git', ['-C', root, 'config', 'user.name', 'TORCH Test']);
writeFileSync(join(root, 'README.md'), '# Console fixture\n');
execFileSync('git', ['-C', root, 'add', '.']);
execFileSync('git', ['-C', root, 'commit', '-m', 'fixture']);
return root;
}
test('SCN-product-site / SCN-dashboard-demo / SCN-torch-brand-surface: public site opens the real Console in a separate demo workspace', () => {
const html = readFileSync(new URL('../../site/index.html', import.meta.url), 'utf8');
const demoHtml = readFileSync(new URL('../../site/demo.html', import.meta.url), 'utf8');
const consoleHtml = readFileSync(new URL('../../site/console.html', import.meta.url), 'utf8');
const styles = readFileSync(new URL('../../site/styles.css', import.meta.url), 'utf8');
const torchMark = readFileSync(new URL('../../site/torch-mark.svg', import.meta.url), 'utf8');
assert.match(html, /
TORCH — an AI fleet shaped by your project<\/title>/);
assert.match(html, /An AI team shaped by your project/);
assert.match(html, /Codex, Claude, Pi, or another local runtime for each role/);
assert.match(html, /href="\/console\.html\?demo=1" target="_blank" rel="noopener">View dashboard demo/);
assert.doesNotMatch(html, /in a new tab/i);
assert.doesNotMatch(html, /dashboard-demo-section|demo-tab-overview/);
assert.match(demoHtml, /TORCH Dashboard<\/title>/);
assert.match(demoHtml, //);
assert.match(demoHtml, /url=\/console\.html\?demo=1/);
assert.match(consoleHtml, /id="demo-banner"[\s\S]*Sample project · Changes stay in this tab/);
assert.match(html, /id="route-toggle"/);
assert.match(html, /Your runtime for each session/);
assert.match(html, /authorized, serialized path/);
assert.match(html, /Codex, Claude, Pi, and local adapters[\s\S]*Live provider gate open/);
assert.match(html, /Lower cache and context costs are a hypothesis/);
assert.match(html, /torch bootstrap/);
assert.doesNotMatch(html, /node bin\/torch\.mjs/);
assert.match(html, /Isolated candidate checks[\s\S]*Clean install gate open/);
assert.match(html, /data-label="Evidence"/);
assert.match(html, /As coordination grows[\s\S]*approve every organization change/i);
assert.doesNotMatch(html, /Request CR-184|terrain streaming|Terrain specialist/);
assert.doesNotMatch(html, /nostr|relay coordination|task lock/i);
assert.match(consoleHtml, /Local Fleet Console/);
assert.match(html, /rel="icon" type="image\/svg\+xml" href="\/torch-mark\.svg"/);
assert.match(consoleHtml, /src="\/torch-mark\.svg"/);
assert.match(styles, /color-scheme: dark/);
const landingScript = readFileSync(new URL('../../site/app.js', import.meta.url), 'utf8');
const demoScript = readFileSync(new URL('../../site/demo.js', import.meta.url), 'utf8');
assert.match(consoleHtml, /src="\/demo\.js"/);
assert.match(demoScript, /TorchConsoleDemo = createWorkspace/);
assert.doesNotMatch(landingScript, /data-demo-tab/);
assert.doesNotMatch(demoScript, /fetch\s*\(|XMLHttpRequest/);
assert.doesNotMatch(landingScript, /fetch\s*\(|XMLHttpRequest/);
assert.match(torchMark, /linearGradient id="flameGrad"/);
assert.match(consoleHtml, /noindex,nofollow/);
assert.match(consoleHtml, /console-rail/);
assert.match(consoleHtml, /id="backlog-board"/);
assert.match(consoleHtml, /id="attention-list"/);
assert.match(consoleHtml, /id="artifact-list"/);
assert.match(consoleHtml, /id="organization-map"/);
assert.match(consoleHtml, /id="organization-lifecycle"/);
assert.match(consoleHtml, /id="organization-proposals"/);
assert.match(consoleHtml, /id="organization-action-status"/);
assert.match(consoleHtml, /id="owner-request-form"/);
assert.match(consoleHtml, /will not create a task, change ownership, or wake\/start the agent/);
assert.match(consoleHtml, /id="owner-request-action-status"/);
assert.match(consoleHtml, /Feedback is previewed with its identity/);
assert.match(consoleHtml, /id="work-view-select"/);
assert.match(consoleHtml, /id="work-view-save"/);
assert.match(consoleHtml, /filters never change tasks/);
assert.match(consoleHtml, /id="initiative-progress"/);
assert.match(consoleHtml, /data-schedule-launcher/);
assert.match(consoleHtml, /data-schedule-launcher-preview/);
assert.match(consoleHtml, /data-schedule-launcher-confirm/);
assert.match(consoleHtml, /A schedule with provider wake enabled may invoke its selected local agent/);
assert.match(consoleHtml, /Feature and milestone progress/);
assert.match(consoleHtml, /FIFO queue · source commit/);
assert.match(consoleHtml, /owner-control-note/);
assert.match(consoleHtml, /Create a task proposal/);
assert.match(consoleHtml, /Session Manager still owns triage and assignment/);
assert.match(consoleHtml, /gates remain separate/);
const consoleScript = readFileSync(new URL('../../site/console.js', import.meta.url), 'utf8');
assert.match(consoleScript, /artifact-feedback/);
assert.match(consoleScript, /feedback\/preview/);
assert.match(consoleScript, /data-feedback-confirm/);
assert.match(consoleScript, /snapshot\.backlogHealth/);
assert.match(consoleScript, /backlog\/tasks\/preview/);
assert.match(consoleScript, /data-task-create-confirm/);
assert.match(consoleScript, /Evidence needs refresh/);
assert.match(consoleScript, /queueOrder/);
assert.match(consoleScript, /Awaiting checks or landing review/);
assert.match(consoleScript, /initializeSavedViews/);
assert.match(consoleScript, /data-review-preview/);
assert.match(consoleScript, /data-review-confirm/);
assert.match(consoleScript, /data-hierarchy-activation-preview/);
assert.match(consoleScript, /data-hierarchy-activation-confirm/);
assert.match(consoleScript, /activate\/preview/);
assert.match(consoleScript, /Commit pilot activation/);
assert.match(consoleScript, /renderLifecycleOrder/);
assert.match(consoleScript, /managers first/);
assert.match(consoleScript, /reports before managers/);
assert.match(consoleScript, /api\/owner-requests\/preview/);
assert.match(consoleScript, /api\/owner-requests'/);
assert.match(consoleHtml, /Send durable request/);
assert.match(styles, /\.owner-request-preview/);
const consoleServer = readFileSync(new URL('../../src/console/server.mjs', import.meta.url), 'utf8');
assert.match(consoleServer, /HIERARCHY_ACTIVATION_PREVIEW_STALE/);
assert.match(consoleServer, /hierarchy\.activatePilot/);
assert.match(consoleServer, /does not create or start identities, launch an AI runtime, or change user systemd state/);
assert.match(consoleServer, /sendOwnerRequest/);
assert.match(styles, /\.organization-review-preview/);
assert.match(styles, /\.lifecycle-orders/);
assert.match(styles, /\.lifecycle-blockers/);
const workViewsScript = readFileSync(new URL('../../site/work-views.js', import.meta.url), 'utf8');
assert.match(workViewsScript, /torch\.dev\/console-saved-views/);
assert.match(workViewsScript, /completed', 'cancelled/);
const workProgressScript = readFileSync(new URL('../../site/work-progress.js', import.meta.url), 'utf8');
assert.match(workProgressScript, /summarizeInitiatives/);
assert.match(workProgressScript, /At risk/);
assert.match(workProgressScript, /cancelled/);
for (const action of [
'data-runtime-profile-preview', 'data-runtime-profile-confirm', 'data-runtime-profile-edit',
]) assert.match(consoleHtml, new RegExp(`