From 82c0205cd3056c7df2262c742f350c14d7f0775c Mon Sep 17 00:00:00 2001 From: Cyber-preacher Date: Fri, 20 Feb 2026 07:41:25 +0400 Subject: [PATCH] hotfix: deploy hardening: quorum correctness, pool auto-advance, faction/formation stability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align proposal pool thresholds to spec: attention quorum via engaged votes, upvote floor via minimum upvote share (remove accidental “+1” semantics). Fix “pool met quorum but didn’t advance” by re-evaluating transitions on tick and ensuring pool → chamber-vote advances immediately once thresholds are met. Correct chamber quorum semantics to explicit “33% + 1 engaged vote”, keep passing as “66.6% + 1 yes within quorum”, and surface quorumNeeded via DTO to prevent client drift. Factions API hardening: cofounder invitations surfaced in DTOs and feed events, channels/threads/messages projections improved (reply counts, message lists), initiatives projection tightened (draft visibility scoped to owner where applicable). Formation flow hardening: block joining ended/suspended/completed projects with explicit API errors, improve finished/ready-to-finish handling and event/timeline emission. Humans/chambers/governance projections tightened for consistency (faction membership, formation participation, tier/active duration fields). Ops ergonomics: expand ops-presets.ts presets for resets (preserve indexer/proof tables, clock-only reset, open testing mode), add schema drift repair helpers for known formation tables/columns. Tests: update quorum/transition unit tests, extend/adjust API regression coverage for factions/formation/humans/governance, add pool denominator/bootstrap regression test. --- src/app/AppRoutes.tsx | 28 ++ src/components/AddressInline.tsx | 23 +- src/components/CardActionsRow.tsx | 25 +- src/components/ProposalPageHeader.tsx | 11 +- src/components/ProposalSections.tsx | 16 +- src/data/vortexopedia.ts | 27 + src/lib/apiClient.ts | 67 ++- src/lib/dtoParsers.ts | 6 +- src/pages/MyGovernance.tsx | 2 +- src/pages/chambers/Chambers.tsx | 36 +- src/pages/factions/Faction.tsx | 472 +++++------------- src/pages/factions/FactionChannel.tsx | 375 ++++++++++++++ src/pages/factions/FactionCreate.tsx | 55 +- src/pages/factions/FactionInitiative.tsx | 293 +++++++++++ .../factions/FactionInitiativeCreate.tsx | 166 ++++++ src/pages/factions/FactionThreadCreate.tsx | 183 +++++++ src/pages/formation/Formation.tsx | 13 +- src/pages/proposals/ProposalChamber.tsx | 18 +- src/pages/proposals/ProposalDraft.tsx | 9 +- src/pages/proposals/ProposalPP.tsx | 32 +- src/pages/proposals/Proposals.tsx | 50 +- src/types/api.ts | 40 ++ 22 files changed, 1532 insertions(+), 415 deletions(-) create mode 100644 src/pages/factions/FactionChannel.tsx create mode 100644 src/pages/factions/FactionInitiative.tsx create mode 100644 src/pages/factions/FactionInitiativeCreate.tsx create mode 100644 src/pages/factions/FactionThreadCreate.tsx diff --git a/src/app/AppRoutes.tsx b/src/app/AppRoutes.tsx index 1d79b23..e17f8d8 100644 --- a/src/app/AppRoutes.tsx +++ b/src/app/AppRoutes.tsx @@ -8,6 +8,10 @@ import Invision from "../pages/invision/Invision"; import Vortexopedia from "../pages/Vortexopedia"; import Factions from "../pages/factions/Factions"; import Faction from "../pages/factions/Faction"; +import FactionChannel from "../pages/factions/FactionChannel"; +import FactionInitiative from "../pages/factions/FactionInitiative"; +import FactionThreadCreate from "../pages/factions/FactionThreadCreate"; +import FactionInitiativeCreate from "../pages/factions/FactionInitiativeCreate"; import FactionCreate from "../pages/factions/FactionCreate"; import ProposalPP from "../pages/proposals/ProposalPP"; import ProposalChamber from "../pages/proposals/ProposalChamber"; @@ -49,6 +53,30 @@ const AppRoutes: React.FC = () => { } /> } /> } /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> } /> } /> } /> diff --git a/src/components/AddressInline.tsx b/src/components/AddressInline.tsx index 3eb872e..21e01d6 100644 --- a/src/components/AddressInline.tsx +++ b/src/components/AddressInline.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { Link } from "react-router"; import { Check, Copy } from "lucide-react"; import { shortAddress } from "@/lib/profileUi"; @@ -38,12 +39,22 @@ export const AddressInline: React.FC = ({ - - {shortAddress(address, size)} - + {address.trim().length > 0 ? ( + + {shortAddress(address, size)} + + ) : ( + + {shortAddress(address, size)} + + )} {showCopy ? ( + ) : null} + {canLeave ? ( + + ) : null} + {isFounderAdmin ? ( + + ) : null} + + + {viewerRole === "founder" ? ( +
+ + Founder leave disabled until transfer + +
+ ) : null} -
- {canJoin ? ( - - ) : null} - {canLeave ? ( - - ) : null} - {viewerRole === "founder" ? ( - Founder leave disabled until transfer - ) : null} - {isFounderAdmin ? ( - - ) : null} +
+ + +
{isFounderAdmin && editOpen ? ( @@ -495,16 +482,21 @@ const Faction: React.FC = () => { channels.map((channel) => (
-
-

{channel.title}

+ +

+ {channel.title} +

#{channel.slug} · {channel.writeScope} · threads{" "} {channel.threadCount}

-
+ {isFounderAdmin ? (