+ ),
+}));
+
+describe("miner coding-agent docs page", () => {
+ it("mounts the docs route and renders the expected sections", async () => {
+ render();
+
+ expect(await screen.findByRole("heading", { name: "Miner coding-agent driver" })).toBeTruthy();
+ expect(screen.getByRole("heading", { name: "Provider selection" })).toBeTruthy();
+ expect(screen.getByRole("heading", { name: "Model and timeout overrides" })).toBeTruthy();
+ expect(
+ screen.getByRole("heading", { name: "Recognizing a stale or missing credential" }),
+ ).toBeTruthy();
+ expect(screen.getByRole("heading", { name: "Related docs" })).toBeTruthy();
+ });
+
+ it("keeps the provider list aligned with the engine's accepted provider names", () => {
+ expect(MINER_CODING_AGENT_PROVIDER_ITEMS.map((item) => item.title)).toEqual([
+ ...CODING_AGENT_DRIVER_NAMES,
+ ]);
+ });
+
+ it("documents every driver env var the page claims to cover", () => {
+ expect(MINER_CODING_AGENT_ENV_ROWS.map((row) => row.name)).toEqual([
+ "MINER_CODING_AGENT_PROVIDER",
+ "MINER_CODING_AGENT_CLAUDE_MODEL",
+ "MINER_CODING_AGENT_CODEX_MODEL",
+ "MINER_CODING_AGENT_TIMEOUT_MS",
+ ]);
+ });
+
+ it("exports the route component used by the route definition", () => {
+ expect(typeof MinerCodingAgentDriverDocs).toBe("function");
+ });
+});
diff --git a/apps/gittensory-ui/src/routes/docs.miner-coding-agent.tsx b/apps/gittensory-ui/src/routes/docs.miner-coding-agent.tsx
new file mode 100644
index 0000000000..67458e507d
--- /dev/null
+++ b/apps/gittensory-ui/src/routes/docs.miner-coding-agent.tsx
@@ -0,0 +1,206 @@
+import { createFileRoute, Link } from "@tanstack/react-router";
+
+import { DocsPage } from "@/components/site/docs-page";
+import { Callout, CodeBlock, FeatureRow } from "@/components/site/primitives";
+
+export const MINER_CODING_AGENT_PROVIDER_ITEMS: Array<{ title: string; description: string }> = [
+ {
+ title: "noop",
+ description:
+ "Fail-closed stub. Useful when you want the miner to stay off or you are running tests.",
+ },
+ {
+ title: "claude-cli",
+ description:
+ "Spawns the local `claude` CLI subprocess. Uses `MINER_CODING_AGENT_CLAUDE_MODEL` when set.",
+ },
+ {
+ title: "codex-cli",
+ description:
+ "Spawns the local `codex` CLI subprocess. Uses `MINER_CODING_AGENT_CODEX_MODEL` when set.",
+ },
+ {
+ title: "agent-sdk",
+ description:
+ "Runs the in-process Agent SDK path. It ignores the model and timeout overrides on this seam.",
+ },
+];
+
+export const MINER_CODING_AGENT_ENV_ROWS: Array<{
+ name: string;
+ appliesTo: string;
+ defaultValue: string;
+ notes: string;
+}> = [
+ {
+ name: "MINER_CODING_AGENT_PROVIDER",
+ appliesTo: "All production provider selection",
+ defaultValue: "unset / empty",
+ notes:
+ "Comma-separated preference list. The first configured name wins; unknown names are skipped.",
+ },
+ {
+ name: "MINER_CODING_AGENT_CLAUDE_MODEL",
+ appliesTo: "claude-cli",
+ defaultValue: "CLI default",
+ notes:
+ "Optional override for the Claude Code subprocess. Ignored by noop, codex-cli, and agent-sdk.",
+ },
+ {
+ name: "MINER_CODING_AGENT_CODEX_MODEL",
+ appliesTo: "codex-cli",
+ defaultValue: "CLI default",
+ notes:
+ "Optional override for the Codex subprocess. Ignored by noop, claude-cli, and agent-sdk.",
+ },
+ {
+ name: "MINER_CODING_AGENT_TIMEOUT_MS",
+ appliesTo: "claude-cli / codex-cli",
+ defaultValue: "120000 ms",
+ notes:
+ "Positive integer wall-clock ceiling. Unset or invalid falls back to the CLI driver's default timeout.",
+ },
+];
+
+export const MINER_CODING_AGENT_TRUST_ROWS: Array<{ title: string; description: string }> = [
+ {
+ title: "claude_code_no_oauth_token",
+ description:
+ "Claude Code cannot find a runtime token. Re-run `claude setup-token` and keep the credential operator-owned.",
+ },
+ {
+ title: "claude_code_error_401",
+ description:
+ "Claude rejected the token. Generate a fresh one with `claude setup-token` and replace the old secret.",
+ },
+ {
+ title: "codex_no_auth",
+ description:
+ "Codex cannot find `auth.json`. Re-run `codex auth` on the mounted CLI home or volume.",
+ },
+ {
+ title: "codex_credential_isolation_required",
+ description:
+ "The Codex home or auth path is not isolated from operator-owned storage. Remove the unsafe override.",
+ },
+];
+
+export const Route = createFileRoute("/docs/miner-coding-agent")({
+ head: () => ({
+ meta: [
+ { title: "Miner coding-agent driver — LoopOver docs" },
+ {
+ name: "description",
+ content:
+ "Enable Claude Code or Codex as the miner's coding-agent driver, and document the provider, model, timeout, and credential troubleshooting paths.",
+ },
+ { property: "og:title", content: "Miner coding-agent driver — LoopOver docs" },
+ {
+ property: "og:description",
+ content:
+ "Enable Claude Code or Codex as the miner's coding-agent driver, and document the provider, model, timeout, and credential troubleshooting paths.",
+ },
+ { property: "og:url", content: "/docs/miner-coding-agent" },
+ ],
+ links: [{ rel: "canonical", href: "/docs/miner-coding-agent" }],
+ }),
+ component: MinerCodingAgentDriverDocs,
+});
+
+export function MinerCodingAgentDriverDocs() {
+ return (
+
+
+ The miner resolves MINER_CODING_AGENT_PROVIDER as a comma-separated preference
+ list. The first configured name wins, unknown names are skipped, and an empty or unset list
+ leaves production construction fail-closed instead of guessing a default backend.
+
+
+
+ This seam is explicit on purpose: if you do not configure a provider, the miner does not
+ silently pick one for you.
+
+
+
Provider selection
+
+
+MINER_CODING_AGENT_TIMEOUT_MS=120000
+
+# Prefer Codex, fall back to Claude.
+MINER_CODING_AGENT_PROVIDER=codex-cli,claude-cli
+MINER_CODING_AGENT_CODEX_MODEL=`}
+ />
+
+ `noop` and agent-sdk ignore the model and timeout knobs. Only the CLI
+ subprocess providers consume them.
+
+
+
Model and timeout overrides
+
+ The only driver-specific knobs today are the provider-specific model overrides and the
+ shared wall-clock timeout. Anything else is task-level orchestration, not provider config.
+
+ The shared troubleshooting table for Claude Code and Codex lives on{" "}
+
+ Self-host AI providers
+
+ . This page keeps the miner-specific reminder: the credential lives on the operator's
+ machine or mounted volume, not in repo config.
+
+
+
+ If the CLI cannot see its credential, the miner cannot spawn a healthy provider. Fix the
+ operator-owned credential path first, then come back to the miner env vars.
+
+
+
Related docs
+
+
+ Miner quickstart by lane — install and verify the
+ miner before you wire a coding agent.
+
+
+ Miner workflow — the rest of the contributor loop
+ after the driver is configured.
+
+
+ Self-host AI providers — the broader
+ credential and provider reference that shares the troubleshooting table above.
+
+
+
+ );
+}
diff --git a/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx b/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx
index 5e7cb37aed..66940f7205 100644
--- a/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx
+++ b/apps/gittensory-ui/src/routes/docs.miner-quickstart.tsx
@@ -2,6 +2,7 @@ import { createFileRoute } from "@tanstack/react-router";
import { DocsPage } from "@/components/site/docs-page";
import { CodeBlock, Callout } from "@/components/site/primitives";
+import { Link } from "@tanstack/react-router";
export const Route = createFileRoute("/docs/miner-quickstart")({
head: () => ({
@@ -40,6 +41,11 @@ function MinerQuickstart() {
only branch metadata (changed file paths, commit messages) is sent to authenticated LoopOver
MCP/API responses.
+
+ If you are setting up Claude Code or Codex as the miner's coding-agent driver, read{" "}
+ Miner coding-agent driver first so the env vars
+ match the provider you actually plan to run.
+
0. Install and sign in (every lane)
diff --git a/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx b/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx
index 75e35f5dbc..a85c1b2fd7 100644
--- a/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx
+++ b/apps/gittensory-ui/src/routes/docs.miner-workflow.tsx
@@ -1,4 +1,5 @@
import { createFileRoute } from "@tanstack/react-router";
+import { Link } from "@tanstack/react-router";
import { DocsPage } from "@/components/site/docs-page";
import { CodeBlock, Callout } from "@/components/site/primitives";
@@ -114,6 +115,10 @@ function MinerWorkflow() {
title="Miner workflow"
description="A deterministic four-step loop. Each step is pure metadata; each output is structured JSON your agent can consume."
>
+
+ If the workflow will spawn Claude Code or Codex, configure that driver first in{" "}
+ Miner coding-agent driver.
+
The mirrored loop
Each step on the left is what the contributor runs; the matching step on the right is what
diff --git a/test/unit/docs-miner-quickstart.test.ts b/test/unit/docs-miner-quickstart.test.ts
index 4670d938de..038fcdad37 100644
--- a/test/unit/docs-miner-quickstart.test.ts
+++ b/test/unit/docs-miner-quickstart.test.ts
@@ -43,6 +43,11 @@ describe("docs miner quickstart page", () => {
expect(source).toMatch(/Choose your lane/);
});
+ it("cross-links to the miner coding-agent driver page for Claude Code / Codex setup", () => {
+ expect(source).toMatch(/Miner coding-agent driver/);
+ expect(source).toMatch(/\/docs\/miner-coding-agent/);
+ });
+
it("maps lanes to the repo's configured participation lane from code", () => {
// These must match ParticipationLane in src/signals/engine.ts so the doc reflects real config.
expect(source).toMatch(/direct_pr/);
@@ -62,7 +67,9 @@ describe("docs miner quickstart page", () => {
expect(source).toMatch(/GITTENSORY_UPLOAD_SOURCE=false/);
expect(source).toMatch(/local absolute paths are redacted/i);
expect(source).toMatch(/public-safe/i);
- expect(normalizedSource).toMatch(/scrubbed of economic and identity signals/i);
+ expect(normalizedSource).toMatch(
+ /scrubbed of economic and identity signals/i,
+ );
});
it("documents validation expectations with the real --validation flag", () => {
diff --git a/test/unit/docs-miner-workflow.test.ts b/test/unit/docs-miner-workflow.test.ts
new file mode 100644
index 0000000000..c4c265af96
--- /dev/null
+++ b/test/unit/docs-miner-workflow.test.ts
@@ -0,0 +1,17 @@
+import { readFileSync } from "node:fs";
+import { resolve } from "node:path";
+import { describe, expect, it } from "vitest";
+
+const MINER_WORKFLOW_PATH = resolve(
+ import.meta.dirname,
+ "../../apps/gittensory-ui/src/routes/docs.miner-workflow.tsx",
+);
+
+describe("docs miner workflow page", () => {
+ const source = readFileSync(MINER_WORKFLOW_PATH, "utf8");
+
+ it("cross-links to the miner coding-agent driver page before the loop steps", () => {
+ expect(source).toMatch(/Miner coding-agent driver/);
+ expect(source).toMatch(/\/docs\/miner-coding-agent/);
+ });
+});
From 7861d4fec3641fb51343c3c3ce76db039280fc5b Mon Sep 17 00:00:00 2001
From: jakearmstrong59
Date: Sun, 12 Jul 2026 19:15:42 +0000
Subject: [PATCH 2/2] docs(miner): remove stale deployment claims
---
packages/gittensory-miner/DEPLOYMENT.md | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/packages/gittensory-miner/DEPLOYMENT.md b/packages/gittensory-miner/DEPLOYMENT.md
index 744f2e164d..2fc2aa9881 100644
--- a/packages/gittensory-miner/DEPLOYMENT.md
+++ b/packages/gittensory-miner/DEPLOYMENT.md
@@ -12,16 +12,9 @@ Two form factors for running `@jsonbored/gittensory-miner`: **laptop mode** (sin
## Coding-agent provider configuration
-For provider selection and model/timeout knobs, see the README section on
-[coding-agent driver configuration](README.md#coding-agent-driver-configuration) and the
-interface-level contract in [`docs/coding-agent-driver.md`](docs/coding-agent-driver.md).
-The short version is:
-
-- `MINER_CODING_AGENT_PROVIDER` is a comma-separated preference list; the first configured name wins.
-- Valid provider names are `noop`, `claude-cli`, `codex-cli`, and `agent-sdk`.
-- `MINER_CODING_AGENT_CLAUDE_MODEL` and `MINER_CODING_AGENT_CODEX_MODEL` only affect their matching CLI providers.
-- `MINER_CODING_AGENT_TIMEOUT_MS` only affects the CLI providers and falls back to `120000` ms when unset or invalid.
-- `noop` and `agent-sdk` ignore the model and timeout knobs.
+For provider selection and the CLI-specific model/timeout overrides, see
+[`README.md`](README.md) and the interface-level contract in
+[`docs/coding-agent-driver.md`](docs/coding-agent-driver.md).
## Laptop mode walkthrough