Add Strain Hospice for graceful low-win strain retirement.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Archive failed epidemiology strains to museum hospice with SQLite persistence, operator/AI/court triggers, breeding and graft guards, topology museum nodes, and Seer plus oath ledger accountability.
This commit is contained in:
AetherForge
2026-06-07 09:26:39 -07:00
parent 894b7a50ae
commit d605ef4adb
18 changed files with 701 additions and 18 deletions

View File

@@ -53,10 +53,11 @@ function StrainNodeMesh({
onGoalPath: boolean;
}) {
const pulseRef = useRef<THREE.Mesh>(null);
const isSuccess = node.branchStatus === 'success' || node.miningContinuity === 'continuous';
const isFailed = node.branchStatus === 'failed' || node.miningContinuity === 'interrupted';
const isMuseum = node.inHospice === true;
const isSuccess = !isMuseum && (node.branchStatus === 'success' || node.miningContinuity === 'continuous');
const isFailed = !isMuseum && (node.branchStatus === 'failed' || node.miningContinuity === 'interrupted');
const baseColor = node.color;
const emissive = isFailed ? '#331111' : baseColor;
const emissive = isMuseum ? '#2a2a30' : isFailed ? '#331111' : baseColor;
const intensity = onGoalPath ? nodeEmissiveIntensity(node) * 1.4 : nodeEmissiveIntensity(node);
const radius = 0.35 + Math.min(node.hostCount, 12) * 0.04;
const opacity = nodeWireOpacity(node);
@@ -114,7 +115,7 @@ function StrainEdgeLine({
return (
<group>
<Line points={[start, end]} color={color} lineWidth={lineWidth} transparent opacity={opacity} />
{success && !failed && (
{success && !failed && edge.weight > 0 && (
<PlaguePulse
start={start}
end={end}
@@ -126,8 +127,17 @@ function StrainEdgeLine({
);
}
export default function FleetTopologyMap({ agents }: { agents: Agent[] }) {
const graph = useMemo(() => buildEpidemiologyGraph(agents), [agents]);
export default function FleetTopologyMap({
agents,
hospiceStrains,
}: {
agents: Agent[];
hospiceStrains?: string[];
}) {
const graph = useMemo(
() => buildEpidemiologyGraph(agents, hospiceStrains),
[agents, hospiceStrains],
);
const layouts = useMemo(() => layoutStrainNodes(graph.nodes), [graph.nodes]);
const positionMap = useMemo(() => {
const map = new Map<string, [number, number, number]>();
@@ -138,6 +148,7 @@ export default function FleetTopologyMap({ agents }: { agents: Agent[] }) {
}, [layouts]);
const goalSet = useMemo(() => new Set(graph.goalPath), [graph.goalPath]);
const museumStrains = graph.nodes.filter((n) => n.inHospice).length;
const plagueEdges = graph.edges.filter((e) => e.weight > 0).length;
const continuousStrains = graph.nodes.filter((n) => n.miningContinuity === 'continuous').length;
const interrupted = graph.interrupted.length;
@@ -171,6 +182,7 @@ export default function FleetTopologyMap({ agents }: { agents: Agent[] }) {
>
<span className="live-beacon on" style={{ display: 'inline-block', marginRight: 8, verticalAlign: 'middle' }} />
STRAIN_EPIDEMIOLOGY // {graph.nodes.length} STRAINS · {plagueEdges} PLAGUE_EDGES
{museumStrains > 0 && ` · ${museumStrains} MUSEUM`}
{graph.goalPath.length > 0 && ` · GOAL_PATH ${graph.goalPath.length}`}
{continuousStrains > 0 && ` · ${continuousStrains} MINING`}
{interrupted > 0 && ` · ${interrupted} INTERRUPTED`}