Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Documentation

on:
push:
branches: [main]
paths:
- "docs/**"
- ".github/workflows/docs.yml"
pull_request:
paths:
- "docs/**"
- ".github/workflows/docs.yml"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: pages-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: docs
steps:
- uses: actions/checkout@v4
- uses: voidzero-dev/setup-vp@v1
with:
working-directory: docs
node-version: "24"
cache: true
run-install: false
- run: vp install --frozen-lockfile
- run: vp check
- run: vp run docs:build
env:
VITEPRESS_BASE: /pyops/
- uses: actions/upload-pages-artifact@v4
if: github.event_name != 'pull_request'
with:
path: docs/.vitepress/dist

deploy:
if: github.event_name != 'pull_request'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
72 changes: 58 additions & 14 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ This is a single repo with three cooperating parts:
all work happens. It has its own `AGENTS.md`/`CLAUDE.md` (Vite+ toolchain notes).
`app/src-tauri/` is the Tauri **desktop shell** that wraps this server in a native
window and packages it into a self-contained bundle (vendored Node + bundled
resources) with self-update — see [`docs/desktop.md`](docs/desktop.md).
- **`mod/`** — the Factorio mod (`pyops`, Factorio 2.0): in-game panel, UDP link to
resources) with self-update — see [`docs/development/desktop.md`](docs/development/desktop.md).
- **`mod/`** — the Factorio mod (`pyops`, Factorio 2.1): in-game panel, UDP link to
the app, data-dump trigger, Helmod-style production-block view, and the
request-combinator planner. Pure Lua, no build step.
- **`scripts/`** — dev-only helpers (currently `tunnel-dev`, to expose the dev
Expand All @@ -38,15 +38,16 @@ dev, a per-OS user-data dir for a packaged build, overridable via `PYOPS_DATA_DI
- `factory-solve.server.ts`, `cost-analysis.server.ts`, `effects.ts`, `additives.ts` — planning logic.
- `agent.ts`, `agent-tools.server.ts` — the AI assistant (AI SDK v6 + OpenRouter,
read-only tools + propose-then-apply writes: draft-a-block, draft-a-plan,
revise-a-block's rate).
and revise a block's rate or recipe set).
- `bridge/` — UDP bridge to the mod. `protocol.ts` defines the wire contract;
**`PROTOCOL_VERSION` must stay in lockstep with the same constant in
`mod/control.lua`** (each side warns on mismatch).
- `solver/` — pure-TS sparse **linear system** per "block" (`block.ts`,
`linalg.ts`). A pinned output goal + `Match` items become equations;
`export`/`import` items are free boundary flows. Recipes and splits are
user-chosen, so there is no LP/optimizer. Handles Py's cyclic recipe chains and
reports fractional building counts.
- `solver/` — the HiGHS-backed linear-program model for each block (`lp.ts`),
constraint diagnosis (`diagnose.ts`), and composed sub-blocks (`subblock.ts`).
Goals, goods made inside the block, and recipe pins become constraints; other
goods remain free boundary flows. Recipes and splits are user-chosen rather than
globally optimized. The solver handles Py's cyclic chains and reports fractional
building counts.
- `db/` — Drizzle ORM over `better-sqlite3`. `schema.ts` is the source of truth;
`import-factorio.ts` loads the dump; `synthesize.ts` builds pass-2 synthetic
recipes (mining/boiling/burning/spoiling/planting/rocket-launch, temperature
Expand Down Expand Up @@ -90,10 +91,50 @@ build` packages a bundle (run `src-tauri/vendor-node.sh` first). Releases are
automated by **release-please** (one product version) — **don't hand-edit the
version** in `version.txt` / `app/package.json` / `Cargo.toml` / `tauri.conf.json` /
`mod/info.json`; it bumps them all in lockstep from conventional commits. See
[`docs/desktop.md`](docs/desktop.md).
[`docs/development/desktop.md`](docs/development/desktop.md).

If setup/runtime/package-manager behavior looks wrong, run `vp env doctor`.

## Documentation site (`docs/`)

`docs/` is a separate Vite+ package that builds the public VitePress site. The
top-level sections are user-facing; subsystem internals live under
`docs/development/`. Keeping this package separate prevents VitePress's Vite
dependency from entering the desktop app's dependency graph.

Run documentation commands from inside `docs/`:

- `vp install` — install the pinned documentation toolchain.
- `vp check` — format, lint, and typecheck documentation sources and config.
- `vp run docs:dev` — start the local documentation server.
- `vp run docs:build` — build the static site and validate internal links.
- `vp run docs:preview` — serve the production build locally.

The GitHub Pages build sets `VITEPRESS_BASE=/pyops/`; local development uses `/`.
The app and docs have independent lockfiles, so run the relevant package's
install/check commands after changing it.

Documentation is a practical manual, not a marketing site:

- Organize user pages around tasks and questions. Lead with the outcome, use the
exact visible UI labels, and state what the user should see after each workflow.
- Assume readers know Factorio production basics, but explain PyOps-specific
concepts and planner terminology when first introduced.
- Prefer current dark-mode screenshots from the real app for UI workflows. Use
localized names and representative project data; never expose API keys, local
paths, personal information, or other secrets in an image.
- Use generated raster illustrations selectively for confusing mental models or
workflows that the UI cannot show. Do not use generated images as fake UI, and
prefer Mermaid/SVG for simple deterministic diagrams.
- Keep screenshots purposeful and maintainable: capture stable states after the
prose is correct rather than illustrating every click.
- Keep published documentation evergreen. Describe the product and architecture
as they exist; do not include issue or PR numbers, commit references,
implementation chronology, migration anecdotes, conversational asides, or
notes about what older versions called something. Put history in GitHub and
the changelog. Mention an upgrade or compatibility distinction only when the
reader must act on it.

## The Factorio mod (`mod/`)

Pure Lua, edited in place — no build step. Key files: `control.lua` (panel +
Expand All @@ -112,7 +153,7 @@ bridge + live-state sync), `summary.lua` (production-block view), `combinator.lu
`.github/workflows/mod-test.yml` (manual — needs a Factorio binary). See
`mod/tests/README.md`. Game-API logic (entities/blueprints/GUI) is still
hands-on.
- Never assume Py mechanics or Factorio 2.0 API behavior — read the data dump or
- Never assume Py mechanics or Factorio 2.1 API behavior — read the data dump or
the relevant Lua and cite the exact value/line.

## Conventions
Expand Down Expand Up @@ -140,7 +181,7 @@ bridge + live-state sync), `summary.lua` (production-block view), `combinator.lu
dynamic imports of server code trip import protection too. The only sanctioned
dynamic imports: heavyweight optional deps (`sharp`), Tauri plugins in client
code, and the bridge server↔handlers cycle guard.
- **UI work follows the design system** — [`docs/design.md`](docs/design.md): theme
- **UI work follows the design system** — [`docs/development/design.md`](docs/development/design.md): theme
tokens (never raw palette colors), the `components/ui` primitives (never
hand-rolled buttons/inputs/badges), square corners, `PageHeader`/`EmptyState`/
`Skeleton`, and loading/empty/error states on every async surface.
Expand All @@ -157,9 +198,12 @@ bridge + live-state sync), `summary.lua` (production-block view), `combinator.lu
change adds/renames/removes a user-facing surface (a page, tab, setting, install
flow, env var, CLI command) or alters how a subsystem works, update the docs in
the same pass:
- User-facing behavior, setup, config → [`README.md`](README.md).
- How a subsystem works → the matching file in [`docs/`](docs/) (architecture,
data-pipeline, solver, bridge, ai-assistant, design).
- User-facing behavior, setup, config → the matching guide in [`docs/`](docs/).
- Product pitch, download path, and contributor entry points →
[`README.md`](README.md).
- How a subsystem works → the matching file in
[`docs/development/`](docs/development/) (architecture, data-pipeline, solver,
bridge, ai-assistant, design).
- A structural or workflow change (new top-level dir, build/verify step,
convention) → this `AGENTS.md`.

Expand Down
172 changes: 74 additions & 98 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,124 +2,100 @@

<img src="app/public/logo.svg" alt="PyOps logo" width="100">

A web-based factory planner and in-game ops assistant for **Factorio**, built for
the **Pyanodons (Py)** overhaul — like [YAFC](https://github.com/Yafc-CE/yafc-ce),
but in the browser, with deep in-game integration and an AI-assisted planner. It
runs locally alongside your Factorio install and reads recipe data straight from
the game; Py-specific views (like TURD) appear only when that data is present, but
it loads whatever mod set you sync.

**Just want to run it?** PyOps ships as a self-updating **desktop app** for Linux,
macOS, and Windows — no toolchain needed. Grab a build from the
[Releases](https://github.com/ApocDev/pyops/releases) page (it still needs Factorio
installed locally to sync recipe data), or [run it from source](#run-it) to hack on
it. Build/release details: [`docs/desktop.md`](docs/desktop.md).

---

## What it does

- **Design production blocks** — set output goals + rates, pick recipes/machines/
modules, and PyOps solves the run-rates and building counts for the whole chain
(cyclic loops, fluid temperatures, byproducts, spoilage). Pin counts, route
byproducts, fold chains into sub-blocks, or extract a recipe into its own block.
- **Balance the whole factory** — every block's imports/exports roll into one
ledger (deficits, surpluses, built-vs-required machines), with what-if. Supply
priorities let recovery blocks feed demand before dedicated fallback production.
- **Explore the data** — a searchable catalogue with a recipe explorer (producers/
consumers ranked and availability-grouped) and a dependency-tree explorer.
- **Track TURD & research** — Py's tech upgrades are first-class; pick a path and
every block re-solves against your research horizon.
- **Plan with AI** — an OpenRouter-backed assistant drafts whole chains, honouring
what you can build now vs. after research, and can read the live factory.
- **Reach into the running game** — a companion mod links over localhost UDP: an
in-game block panel, locate, live sync of research/TURD/machines, and more.
- **Quality of life** — command palette (Ctrl+K), undo (Ctrl+Z), per-block
snapshots, backup/share, tasks & notes, light/dark theme, responsive to phone.

Each subsystem has its own doc under [`docs/`](#documentation).

---
PyOps is a local factory planner and in-game operations assistant for
**Factorio**. It is designed around the **Pyanodons** mods, but works with vanilla
Factorio and other mod packs by synchronizing recipes, technologies, machines,
and icons from your own game.

## Screenshots
**[Read the PyOps documentation →](https://apocdev.github.io/pyops/)**

**Factory ledger** — every block's flows in one balance sheet; deficits rank by %
of demand met.
![Factory ledger — whole-factory balance with deficits, surpluses, and built-vs-required machines](docs/images/factory.png)
Installation, first project, planning workflows, game integration, reference,
and troubleshooting.

**Block editor** — goals in, solved rates and building counts out; toggle recipes/
blocks off, fold into sub-blocks, or switch to a flow diagram.
![Block editor — the Basic substrate bio-chain, solved with byproducts](docs/images/block-editor.png)
**[Download the latest release →](https://github.com/ApocDev/pyops/releases)**

**AI assistant** — drafts a whole block from a goal, flagging byproducts, spoilage,
and TURD upgrades.
![AI assistant drafting a py science 1 production block](docs/images/assistant.png)
Self-updating desktop builds for Linux, macOS, and Windows.

**Browse** — every item, fluid, and recipe with produced-by / used-in, grouped by
availability and annotated with waste %.
![Browse — Iron plate with its producers and consumers](docs/images/browse.png)
## What PyOps does

---
- **Design production blocks** — set output goals and rates, choose recipes and
machines, and solve full production chains including cycles, byproducts,
spoilage, and fluid temperatures.
- **Balance the factory** — combine every block's imports and exports in one
ledger, identify shortfalls and surpluses, and test changes with what-if plans.
- **Explore game data** — search items, fluids, recipes, producers, consumers,
and dependency trees from the mod set you actually use.
- **Plan around progression** — model research horizons and, when present,
Pyanodons TURD choices throughout the factory.
- **Connect to Factorio** — use the companion mod for live research, machine,
location, and production-plan integration.
- **Draft with the Assistant** — optionally use an OpenRouter-backed planning
assistant that understands the current project and can propose production
blocks for review.

## Run it
The [planning guide](https://apocdev.github.io/pyops/guide/) explains how these
parts fit into a complete workflow.

```bash
cd app
vp install # install dependencies (Node LTS + pnpm; Vite+ handles the rest)
vp dev # start PyOps at http://localhost:3000
```
## Screenshots

**Factory ledger** — the balance across every production block, including
deficits, surpluses, and machine requirements.

Then open **⚙ Settings › Game data** and run a sync: PyOps launches Factorio
headlessly, reads its recipe data, and loads it into a local database (~1–2 min the
first time). Needs **Factorio 2.1** with the **Pyanodons** suite +
**pypostprocessing**.
![Factory ledger showing whole-factory balance](docs/images/factory.png)

- **Configuration** (env vars, remote access): [`docs/configuration.md`](docs/configuration.md)
- **In-game features** (companion mod, launching the bridge): [`docs/bridge.md`](docs/bridge.md)
- **AI assistant** needs an [OpenRouter](https://openrouter.ai) key (set it in
Settings or `OPENROUTER_API_KEY`).
**Block editor** — goals in, solved rates and building counts out.

The dev server also exposes the PyOps MCP tool surface at
`http://localhost:3000/mcp` (project configs for Codex and Claude Code ship in the
repo).
![Block editor showing a solved production chain](docs/images/block-editor.png)

---
**Assistant** — project-aware help for investigating and drafting production
plans.

## Documentation
![Assistant drafting a production block](docs/images/assistant.png)

How PyOps works under the hood lives in [`docs/`](docs/):
## Developing PyOps

- [Architecture](docs/architecture.md) — the one-app-plus-mod model and repo layout.
- [Data pipeline](docs/data-pipeline.md) — how the Factorio data sync works.
- [Block solver](docs/solver.md) — the planning math.
- [Factorio bridge](docs/bridge.md) — the in-game link and its setup.
- [AI assistant](docs/ai-assistant.md) — the planning agent.
- [Configuration](docs/configuration.md) — environment variables and remote access.
- [Desktop app](docs/desktop.md) — how the Tauri bundle is built and released.
The repository contains three cooperating parts:

Contributing: `vp check` and `vp test` must be clean; the mod (`mod/`) is pure Lua,
no build step. See [`AGENTS.md`](AGENTS.md) for the full toolchain and conventions.
- `app/` — the TanStack Start application and Tauri desktop shell;
- `mod/` — the Factorio companion mod;
- `docs/` — the VitePress documentation site.

---
Start the application from source with [Vite+](https://viteplus.dev/):

## Credits & inspiration
```bash
cd app
vp install
vp dev
```

Run `vp check` and `vp test` from `app/` before submitting application changes.
The companion mod is pure Lua and has no build step.

For architecture, subsystem contracts, desktop packaging, and contributor
workflows, read the hosted
[development documentation](https://apocdev.github.io/pyops/development/).
Repository-specific agent conventions remain in [`AGENTS.md`](AGENTS.md).

To work on the documentation site:

```bash
cd docs
vp install
vp run docs:dev
```

- **[YAFC](https://github.com/Yafc-CE/yafc-ce)** — the planner model, cost-analysis
approach, and the "design blocks, balance the factory" shape.
- **[Helmod](https://mods.factorio.com/mod/helmod)** — the in-game production-block
panel is heavily inspired by Helmod's; no Helmod assets are bundled.
- **[Factory Search](https://mods.factorio.com/mod/FactorySearch)** — the "locate in
game" feature relays to its remote interface.
- **[pypostprocessing](https://mods.factorio.com/mod/pypostprocessing)** — makes a
clean, planner-friendly data dump possible.
## Credits and inspiration

---
- **[YAFC](https://github.com/Yafc-CE/yafc-ce)** — the planner model,
cost-analysis approach, and the design-blocks/balance-factory workflow.
- **[Helmod](https://mods.factorio.com/mod/helmod)** — inspiration for the
in-game production-block panel; no Helmod assets are bundled.
- **[Factory Search](https://mods.factorio.com/mod/FactorySearch)** — the locate
action can relay to its remote interface.
- **[pypostprocessing](https://mods.factorio.com/mod/pypostprocessing)** —
supplies additional planner-oriented metadata for Pyanodons data dumps.

## License

Free software under the **GNU General Public License v3.0** — see [`LICENSE`](LICENSE).
Copyright (C) 2026 ApocDev. You're free to use, study, modify, and share it
(including commercially), but any distributed version or derivative must stay open
under the same GPLv3 terms — matching [YAFC](https://github.com/Yafc-CE/yafc-ce) and
[Helmod](https://mods.factorio.com/mod/helmod). Contributions accepted under the same
license.
PyOps is free software under the **GNU General Public License v3.0**. See
[`LICENSE`](LICENSE). Copyright (C) 2026 ApocDev.
2 changes: 1 addition & 1 deletion app/src/components/context-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { cn } from "#/lib/utils.ts";

/**
* Right-click context menu shell (docs/design.md): a Radix `DropdownMenu`
* Right-click context menu shell (docs/development/design.md): a Radix `DropdownMenu`
* anchored at the pointer, so Escape-to-close, focus containment/roving,
* `role="menu"` semantics, and click-away come from the primitive rather than a
* hand-rolled backdrop (#86). Callers stay declarative — own the open state and
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/empty-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { LucideIcon } from "lucide-react";
import { cn } from "#/lib/utils.ts";

/**
* The one empty-state component (docs/design.md): say what's missing and, via
* The one empty-state component (docs/development/design.md): say what's missing and, via
* `action`, how to fill it. Async surfaces must never render blank.
*/
export function EmptyState({
Expand Down
Loading
Loading