();
+ return {
+ ...actual,
+ Link: ({ to, children }: { to: string; children: ReactNode }) => {children},
+ };
+});
+
+vi.mock("@/components/site/docs-page", () => ({
+ DocsPage: ({ children, title }: { children: ReactNode; title: string }) => (
+
+
{title}
+ {children}
+
+ ),
+}));
+
+vi.mock("@/components/site/primitives", () => ({
+ Callout: ({ children, title }: { children: ReactNode; title?: string }) => (
+
+ {title ? {title} : null}
+ {children}
+
+ ),
+ CodeBlock: ({ code }: { code: string }) => {code},
+ FeatureRow: ({ items }: { items: Array<{ title: string; description: string }> }) => (
+
+ {items.map((item) => (
+
+
- {item.title}
+ - {item.description}
+
+ ))}
+
+ ),
+}));
+
+vi.mock("@/components/site/workflow-mirror", () => ({
+ WorkflowMirror: () => ,
+}));
+
+// Every route that embeds the shared callout, so a new route add/remove can't silently skip one (#5191).
+const ROUTES_WITH_CALLOUT: ReadonlyArray<[string, () => ReactNode]> = [
+ ["/docs/self-hosting-operations", SelfHostingOperations],
+ ["/docs/miner-quickstart", MinerQuickstart],
+ ["/docs/miner-workflow", MinerWorkflow],
+];
+
+describe("AMS observability cross-reference callout", () => {
+ it("renders a link to the Observing your miner guide", () => {
+ render();
+ const link = screen.getByRole("link", { name: "Observing your miner" });
+ expect(link.getAttribute("href")).toBe(AMS_OBSERVABILITY_DOC_URL);
+ });
+
+ it("targets a well-formed, non-empty absolute https URL (guards against a blank/copy-paste link)", () => {
+ expect(AMS_OBSERVABILITY_DOC_URL).toBeTruthy();
+ const url = new URL(AMS_OBSERVABILITY_DOC_URL);
+ expect(url.protocol).toBe("https:");
+ expect(url.hostname).toBe("github.com");
+ });
+
+ it.each(ROUTES_WITH_CALLOUT)("wires the callout into %s", (_path, RouteComponent) => {
+ const { container } = render();
+ const link = container.querySelector(`a[href="${AMS_OBSERVABILITY_DOC_URL}"]`);
+ expect(link).not.toBeNull();
+ expect(link?.textContent).toBe("Observing your miner");
+ });
+});
diff --git a/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx b/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx
index 385848b25c..183f0ea76d 100644
--- a/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx
+++ b/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx
@@ -1,5 +1,6 @@
import { createFileRoute } from "@tanstack/react-router";
+import { AmsObservabilityCallout } from "@/components/site/ams-observability-callout";
import { DocsPage } from "@/components/site/docs-page";
import { CodeBlock, Callout } from "@/components/site/primitives";
import { Link } from "@tanstack/react-router";
@@ -26,7 +27,7 @@ export const Route = createFileRoute("/docs/miner-quickstart")({
component: MinerQuickstart,
});
-function MinerQuickstart() {
+export function MinerQuickstart() {
return (
miner workflow for the full loop and{" "}
privacy & security for the boundary details.
+
);
}
diff --git a/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx b/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx
index a85c1b2fd7..f1d3c333ed 100644
--- a/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx
+++ b/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx
@@ -1,6 +1,7 @@
import { createFileRoute } from "@tanstack/react-router";
import { Link } from "@tanstack/react-router";
+import { AmsObservabilityCallout } from "@/components/site/ams-observability-callout";
import { DocsPage } from "@/components/site/docs-page";
import { CodeBlock, Callout } from "@/components/site/primitives";
import { WorkflowMirror, type MirroredStep } from "@/components/site/workflow-mirror";
@@ -25,7 +26,7 @@ export const Route = createFileRoute("/docs/miner-workflow")({
component: MinerWorkflow,
});
-function MinerWorkflow() {
+export function MinerWorkflow() {
const steps: MirroredStep[] = [
{
title: "Plan",
@@ -136,6 +137,7 @@ function MinerWorkflow() {
commits, prefer cleaning open work over opening more — risk-adjusted priority is part of the
score model.
+
);
}
diff --git a/apps/gittensory-ui/src/routes/docs.self-hosting-operations.tsx b/apps/gittensory-ui/src/routes/docs.self-hosting-operations.tsx
index c94fdba420..e7862a0b0e 100644
--- a/apps/gittensory-ui/src/routes/docs.self-hosting-operations.tsx
+++ b/apps/gittensory-ui/src/routes/docs.self-hosting-operations.tsx
@@ -1,5 +1,6 @@
import { createFileRoute, Link } from "@tanstack/react-router";
+import { AmsObservabilityCallout } from "@/components/site/ams-observability-callout";
import { DocsPage } from "@/components/site/docs-page";
import { Callout, CodeBlock, FeatureRow } from "@/components/site/primitives";
@@ -25,7 +26,7 @@ export const Route = createFileRoute("/docs/self-hosting-operations")({
component: SelfHostingOperations,
});
-function SelfHostingOperations() {
+export function SelfHostingOperations() {
return (
+
Host clock sync (NTP)