feat: complete evidence restructuring worktree

This commit is contained in:
Codex
2026-08-26 11:39:02 +02:00
parent a54d4769dd
commit 38f02cfd08
56 changed files with 1981 additions and 1801 deletions
@@ -159,6 +159,7 @@ test("opens Workspace management from the right sidebar without interrupting the
server.use(
http.get("/api/workspace-registry/status", () =>
HttpResponse.json({ branch: "main", ahead: 0, behind: 0, degraded: false })),
http.get("/api/health/dwh", () => HttpResponse.json({ ok: false })),
);
renderShell();
@@ -168,6 +169,21 @@ test("opens Workspace management from the right sidebar without interrupting the
expect(screen.getByTestId("app-shell")).toHaveAttribute("data-activity-layout", "closed");
});
test("does not block the shell when the DWH is unavailable at startup", async () => {
let healthChecks = 0;
server.use(
http.get("/api/health/dwh", () => {
healthChecks += 1;
return HttpResponse.json({ ok: false });
}),
);
renderShell();
expect(await screen.findByRole("button", { name: "Workspace management" })).toBeVisible();
expect(screen.queryByRole("heading", { name: "Connection unavailable" })).not.toBeInTheDocument();
expect(healthChecks).toBe(0);
});
test("marks the composer as awaiting input for a pending freetext gate", () => {
useSessionStore.setState({
-36
View File
@@ -23,7 +23,6 @@ import { toast } from "sonner";
import {
closeSession, listSessions, resumeSession, getSession,
renameSession, setSessionGroup, archiveSession, unarchiveSession, deleteSession, prewarmRuntime,
checkDwhHealth,
} from "../api/sessions";
import { logout as logoutUser } from "../api/auth";
import {
@@ -129,23 +128,8 @@ export function AppShell({ canLogout }: AppShellProps) {
const [stopConfirm, setStopConfirm] = useState(false);
const [collapsedGroups, setCollapsedGroups] = useState<Record<string, boolean>>({});
const [renameGroupTarget, setRenameGroupTarget] = useState<string | null>(null);
const [dwhDown, setDwhDown] = useState(false);
const [dwhChecking, setDwhChecking] = useState(true);
const [dwhCheckEpoch, setDwhCheckEpoch] = useState(0);
const operationEpochRef = useRef(0);
useEffect(() => () => { operationEpochRef.current += 1; }, []);
useEffect(() => {
let cancelled = false;
const operation = captureAuthOperation({ disposalEpoch: operationEpochRef.current });
if (!operation) return () => { cancelled = true; };
setDwhChecking(true);
checkDwhHealth().then((r) => {
if (cancelled || !isAuthOperationCurrent(operation, { disposalEpoch: operationEpochRef.current })) return;
setDwhDown(!r.ok);
setDwhChecking(false);
});
return () => { cancelled = true; };
}, [dwhCheckEpoch]);
const groups = useMemo(
() => [...new Set(sessions.map((s) => s.group).filter((g): g is string => !!g))].sort(),
@@ -958,26 +942,6 @@ export function AppShell({ canLogout }: AppShellProps) {
}}
/>
)}
{dwhDown && (
<Dialog open onOpenChange={() => {}}>
<DialogContent showCloseButton={false} className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Connection unavailable</DialogTitle>
<DialogDescription>
The database is unreachable. Check the VPN connection and try again.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button
disabled={dwhChecking}
onClick={() => setDwhCheckEpoch((e) => e + 1)}
>
{dwhChecking ? "Checking…" : "Retry"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)}
</div>
);
}
+1 -1
View File
@@ -197,7 +197,7 @@ function PiInstructionSteps({ details }: { details: PiPlatformDetails }) {
</li>
<li>
<h4 className="font-semibold text-foreground">Edit the provider catalog</h4>
<p className="mt-1 text-muted-foreground">Edit <code>{details.modelsPath}</code> only when adding or correcting a provider/model definition. The provider catalog is an address book/map of the services Pi can call: each entry supplies the API endpoint and format, and lists the model identifiers offered there. It does not enable a model and never contains credentials.</p>
<p className="mt-1 text-muted-foreground">Edit <code>{details.modelsPath}</code> only when adding or correcting a provider/model definition. The provider catalog is an address book/map of the services Pi can call: each entry supplies the API endpoint and format, and lists the model identifiers offered there. It does not enable a model and never contains credentials. Provider integrations must remain declarative; do not add model-provider code under <code>harness/.pi/extensions/</code>.</p>
<dl className="mt-2 grid grid-cols-[auto_1fr] gap-x-2 gap-y-1 text-muted-foreground">
<dt className="font-mono text-foreground">baseUrl </dt><dd>is the provider API endpoint.</dd>
<dt className="font-mono text-foreground">api </dt><dd>selects the provider API format.</dd>