You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(ui): replace 49 hand-rolled docs.*.tsx thin routes with one dynamic docs.$slug.tsx route (#8182)
Every docs page carried an identical hand-rolled TanStack route file: a loader
calling getDocPage, head/og meta duplicating the .mdx frontmatter's own
title/description, and the same DocsPage + Suspense/LoadingState body. Adding
a page meant touching 5+ files and regenerating the route tree; two tests
pinned the route-file count and had to be bumped on every addition.
- One dynamic docs.$slug.tsx route replaces all 49 per-page files. title/
description come from frontmatter (already did); eyebrow (the one real
per-page datum, previously a hand-copied JSX prop) moves into frontmatter
too, via a new required field in source.config.ts's page schema.
- docs.index.tsx (a real static page) and docs.fumadocs-spike-api-reference.tsx
(a standalone Scalar widget, not DocsPage/MDX at all) stay as their own
routes -- audited, neither is boilerplate this replaces.
- Every literal `to="/docs/<slug>"` Link across the app (nav sidebar, footer,
header dropdown, home page, install flow, agents/miners/maintainers pages)
now uses the typed `to="/docs/$slug" params={{ slug }}` form instead --
done properly with real params, not a type-erasing cast, including fixing
two pre-existing `as "/docs"` casts in docs-nav.tsx/docs.index.tsx found
along the way.
- docs.miner-coding-agent.tsx's three exported data arrays (asserted against
by a test, unrelated to routing) moved to
src/lib/miner-coding-agent-docs-data.ts; their test moved alongside them.
- The two route-file-count-pinning tests (docs-source-server-isolation,
docs-routes-loading-state) now assert the single dynamic route's shape
instead of a per-page count.
- Three test-only `Link` mocks (docs.ams-observability-callout,
install, install.permissions) updated to interpolate $-params the same
way the real router resolves them, so their href assertions stay faithful.
Verified in the browser: real docs pages render correctly (title/eyebrow/
description/MDX content), sidebar nav renders + highlights the active page,
client-side navigation works, a nonexistent slug renders a real 404, the
docs index and the untouched Scalar API route both still work.
Closes#8151.
Copy file name to clipboardExpand all lines: apps/loopover-ui/content/docs/ams-config-precedence.mdx
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
---
2
2
title: Miner config precedence
3
3
description: How AMS layers configuration across per-repo goal spec, operator env, CLI flags, and operator policy files -- the order each concern actually implements today.
4
+
eyebrow: Maintainers
4
5
---
5
6
6
7
AMS does **not** have a single `config.js` resolver. Configuration is layered by concern across
@@ -87,8 +88,8 @@ First existing file wins (engine `MINER_GOAL_SPEC_FILENAMES`):
87
88
88
89
<Calloutvariant="warn">
89
90
This is an **AND** requirement, not "last writer wins". Either side missing or malformed →
90
-
dry-run. There is also **no CLI flag wired to governor live mode** today —
Copy file name to clipboardExpand all lines: apps/loopover-ui/content/docs/ams-deployment.mdx
+11-10Lines changed: 11 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
---
2
2
title: AMS deployment guide
3
3
description: Deploy @loopover/miner in laptop mode (single machine, zero Docker) or fleet mode (containerized workers) -- both 100% client-side, credentials never baked into images.
4
+
eyebrow: Maintainers
4
5
---
5
6
6
7
Two form factors for running `@loopover/miner`: **laptop mode** (single machine, zero Docker) and
description: How a loopover-miner instance opts into the optional hosted discovery-index plane, what it may send, and what never leaves the operator's machine.
4
+
eyebrow: Maintainers
4
5
---
5
6
6
7
Operator-facing guide for the **optional** hosted discovery-index plane. This is the client/miner
Copy file name to clipboardExpand all lines: apps/loopover-ui/content/docs/ams-env-reference.mdx
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
---
2
2
title: AMS environment variable reference
3
3
description: Every LOOPOVER_MINER_* / MINER_* env var the miner reads, where it's first referenced in code, and its default -- generated from source, never hand-copied.
Copy file name to clipboardExpand all lines: apps/loopover-ui/content/docs/ams-fleet-manifest.mdx
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,10 @@
1
1
---
2
2
title: Fleet run-manifest
3
3
description: The top-level config a fleet operator authors to run the miner across many repos at once -- which repos are in scope and how the worktree/concurrency budget is split.
4
+
eyebrow: Maintainers
4
5
---
5
6
6
-
The **fleet run-manifest** is the top-level config a *fleet operator* authors to run the miner
7
+
The **fleet run-manifest** is the top-level config a _fleet operator_ authors to run the miner
7
8
across many repos at once: it declares which repos are in scope for a fleet run and how a finite
8
9
worktree/concurrency budget is split between them. It is parsed by
9
10
`parseFleetRunManifestContent` / `parseFleetRunManifest` in `@loopover/engine`
@@ -50,7 +51,7 @@ opposite direction of intent:
50
51
51
52
This module produces only the parsed, typed manifest. Driving the fleet concurrency allocator
52
53
from it is the allocator's own concern, and the cross-repo `portfolio-queue.js` backlog reads the
53
-
same repo list — both *consume* this manifest; neither wiring lives here.
54
+
same repo list — both _consume_ this manifest; neither wiring lives here.
Copy file name to clipboardExpand all lines: apps/loopover-ui/content/docs/ams-goal-spec.mdx
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
---
2
2
title: "MinerGoalSpec (.loopover-miner.yml)"
3
3
description: Per-repo configuration telling an autonomous LoopOver miner what to look for and how to behave when targeting a repo -- the full field reference.
4
+
eyebrow: Maintainers
4
5
---
5
6
6
7
Per-repo configuration telling an autonomous LoopOver miner what to look for and how to behave
@@ -17,8 +18,8 @@ Discovery order (first match wins):
17
18
-`.github/loopover-miner.json`
18
19
19
20
<Calloutvariant="note">
20
-
Every field is optional. Unknown keys are ignored; a malformed field falls back to its
21
-
documented default with a warning — a broken file never hard-fails the miner.
21
+
Every field is optional. Unknown keys are ignored; a malformed field falls back to its documented
22
+
default with a warning — a broken file never hard-fails the miner.
22
23
</Callout>
23
24
24
25
## Relationship to `.loopover.yml`
@@ -113,13 +114,12 @@ Per-repo kill-switch consulted by the Governor chokepoint before every write act
113
114
Per-repo dry-run/live execution opt-in consulted by the Governor chokepoint.
114
115
115
116
<Calloutvariant="warn">
116
-
A freshly-configured miner always defaults to dry-run (observe/log only, never execute a
117
-
write) — this field is the only per-repo path to live mode, and it alone is not sufficient: the
118
-
miner's own operator must also separately opt in globally (env var
119
-
`LOOPOVER_MINER_LIVE_MODE=live`) before writes actually execute. A repo that wants to guarantee
120
-
it never receives live automated writes, regardless of any operator's global setting, should use
121
-
`killSwitch.paused: true` instead — the kill-switch always takes precedence over any live-mode
122
-
opt-in.
117
+
A freshly-configured miner always defaults to dry-run (observe/log only, never execute a write) —
118
+
this field is the only per-repo path to live mode, and it alone is not sufficient: the miner's own
119
+
operator must also separately opt in globally (env var `LOOPOVER_MINER_LIVE_MODE=live`) before
120
+
writes actually execute. A repo that wants to guarantee it never receives live automated writes,
121
+
regardless of any operator's global setting, should use `killSwitch.paused: true` instead — the
122
+
kill-switch always takes precedence over any live-mode opt-in.
123
123
</Callout>
124
124
125
125
-`liveModeOptIn` (string or `null`, default: `null`) — must equal EXACTLY the literal `"live"` to
Copy file name to clipboardExpand all lines: apps/loopover-ui/content/docs/ams-operations-runbook.mdx
+11-14Lines changed: 11 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
---
2
2
title: AMS operations runbook
3
3
description: Recover from SQLite lock contention, ledger corruption, and post-upgrade schema migrations in loopover-miner's local state.
4
+
eyebrow: Maintainers
4
5
---
5
6
6
7
Operator-facing runbook for **local SQLite state**: what the concurrency guarantees actually mean,
@@ -45,7 +46,7 @@ Default **5000 ms**; overridable per-test only — production stores always use
45
46
{
46
47
title: "Two short-lived writers, same file",
47
48
description:
48
-
"E.g. a CLI command finishing while loop is idle, or Grafana reading while the miner appends. SQLite waits up to 5 seconds for the lock, then proceeds or surfaces \"database is locked\".",
49
+
'E.g. a CLI command finishing while loop is idle, or Grafana reading while the miner appends. SQLite waits up to 5 seconds for the lock, then proceeds or surfaces "database is locked".',
49
50
},
50
51
{
51
52
title: "Append-only ledgers",
@@ -67,9 +68,8 @@ Default **5000 ms**; overridable per-test only — production stores always use
67
68
68
69
<Calloutvariant="warn">
69
70
**Invariant:** one active loop (or one intentional writer set) per state directory. Horizontal
70
-
scale = **isolated state dirs** — separate compose projects, separate
71
-
`LOOPOVER_MINER_CONFIG_DIR`, or the Kubernetes StatefulSet pattern in the [AMS deployment
72
-
guide](/docs/ams-deployment).
71
+
scale = **isolated state dirs** — separate compose projects, separate `LOOPOVER_MINER_CONFIG_DIR`,
72
+
or the Kubernetes StatefulSet pattern in the [AMS deployment guide](/docs/ams-deployment).
73
73
</Callout>
74
74
75
75
Quick health check — `doctor` includes `laptop-state-sqlite` (file exists + readable) and
@@ -118,9 +118,9 @@ Re-run `loopover-miner doctor`. If locks persist with a single process, see **Le
118
118
below.
119
119
120
120
<Calloutvariant="note">
121
-
Claims are local bookkeeping only. Two miners on different machines claiming the same GitHub
122
-
issue is a **fleet coordination** problem (duplicate-cluster adjudication in the engine), not
123
-
something SQLite resolves — split state dirs and use operational claim hygiene.
121
+
Claims are local bookkeeping only. Two miners on different machines claiming the same GitHub issue
122
+
is a **fleet coordination** problem (duplicate-cluster adjudication in the engine), not something
123
+
SQLite resolves — split state dirs and use operational claim hygiene.
124
124
</Callout>
125
125
126
126
## Backup and restore
@@ -158,7 +158,7 @@ loopover-miner doctor --json # verify afterward`}
158
158
/>
159
159
160
160
It also removes any leftover `-wal`/`-shm` sidecar files from the live directory after restoring
161
-
each store — those hold in-flight writes from *before* the restore, and leaving them in place
161
+
each store — those hold in-flight writes from _before_ the restore, and leaving them in place
162
162
would let SQLite silently replay stale pre-restore writes back on top of the freshly restored
163
163
file on next open.
164
164
@@ -184,10 +184,7 @@ Check disk space, permissions (`0600` file, `0700` parent), and backup tools cop
184
184
**Remediation.** Stop the miner, then back up the whole state directory (even damaged files help
185
185
post-mortems):
186
186
187
-
<CodeBlock
188
-
lang="bash"
189
-
code={`cp -a "$STATE_DIR" "\${STATE_DIR}.bak.$(date +%Y%m%d%H%M%S)"`}
190
-
/>
187
+
<CodeBlocklang="bash"code={`cp -a "$STATE_DIR" "\${STATE_DIR}.bak.$(date +%Y%m%d%H%M%S)"`} />
191
188
192
189
Choose a recovery tier:
193
190
@@ -267,8 +264,8 @@ tarball, pin the previous package version, and file an issue with the failing `u
0 commit comments