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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
python-version: "3.12"
cache: pip
- name: Install
run: python -m pip install -e '.[dev,quantum]'
run: python -m pip install -e '.[dev,quantum,web]'
- name: Test
run: pytest
- name: Lint
Expand All @@ -38,9 +38,9 @@ jobs:
python-version: "3.12"
cache: pip
- name: Install
run: python -m pip install -e '.[dev]'
run: python -m pip install -e '.[dev,web]'
- name: Test
run: pytest tests/test_problems.py tests/test_new_families.py tests/test_identity.py tests/test_capabilities.py tests/test_json_contract.py tests/test_cli.py tests/test_experiments.py tests/test_bqm.py tests/test_family_qaoa.py tests/test_campaigns.py tests/test_analysis.py tests/test_sense_and_historical.py
run: pytest tests/test_problems.py tests/test_new_families.py tests/test_identity.py tests/test_capabilities.py tests/test_json_contract.py tests/test_cli.py tests/test_experiments.py tests/test_bqm.py tests/test_family_qaoa.py tests/test_campaigns.py tests/test_analysis.py tests/test_sense_and_historical.py tests/web
- name: Lint
run: ruff check .
- name: Formatting
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ data/artifacts/*
/experiments/
/artifacts/
/data/examples/
/data/reports/
/reports/

# Legacy/root-level runtime paths used by older local invocations.
/variaq.db
Expand Down
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,46 @@
VariaQ follows semantic versioning while pre-1.0. Release dates will be added
when a public release is created.

## 0.7.0 — local web UI

- Added an optional, local-first web interface (`pip install 'variaq[web]'`,
then `variaq web`) for inspecting capabilities, problems, runs, campaigns,
analysis, and reports. The UI is a presentation layer over VariaQ's existing
application services; it queries no database directly from the browser and
recomputes no scientific results.
- Added a shared application/service facade (`variaq.services`) used by the web
server and available to future integrations, with bounded, offset-paginated,
filterable run and problem listings.
- Added additive, read-only query methods to `ExperimentStore`
(`query_runs`, `iter_problem_summaries`, `iter_problem_run_summaries`,
`get_problem_definition`, `problem_run_count`) and reverse-lookup methods to
`CampaignStore` (`campaigns_for_run`, `campaigns_for_problem`). Existing run
records, problem artifacts, and schema version `1` are untouched.
- Added a versioned local JSON API under `/api/v1/`, independent of the CLI
`schema_version`.
- Added `variaq web` CLI command with loopback-only default (`127.0.0.1:8701`)
and a prominent warning when binding to a non-loopback address. The 0.7 UI is
local-first software and makes no internet-facing security claim.
- Added `variaq.web` with a FastAPI application, Jinja2 templates, a vendored
Chart.js for campaign-scaling charts, and no Node.js requirement at runtime.
- Campaign planning precedes execution in the UI. Campaign execution is local,
sequential, one-at-a-time, and owned by the server process; VariaQ's
default max-run guard (500 runs) is never bypassed and surfaces as a
requiring-override state in the UI.
- Added run detail, problem detail, campaign detail, analysis, report, and
capabilities pages with objective/expectation/BQM energy displayed as distinct
labeled quantities, provenance (campaign membership, rerun lineage, source-run
counts), and empty states for a fresh install.
- Added safe report downloads confined to files registered to a known report
artifact inside the configured reports root; path traversal is rejected.
- Added `docs/web-ui.md` and `docs/web-ui-architecture.md`.
- Added 46 web tests (`tests/web/`) covering the API, campaign plan/run,
analysis, report flow, scientific label contracts, loopback defaults, remote
bind warnings, traversal, malformed input, empty states, and a regression
guard that capability/status reads never mutate experiment storage.
- No Triagewall, Ollama Fleet, bb scheduling, physical-QPU, or cloud-provider
code was added; `bb-plugin-variaq` is untouched.

## 0.6.0 — campaigns, analysis, and reporting

- Added domain-neutral `ExperimentCampaign` definitions with deterministic IDs,
Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ results, and is designed to grow through problem, solver, backend, and adapter
boundaries.

VariaQ is not a claim of quantum advantage, production scheduler, distributed
service, hardware benchmark based on simulator speed, web service, telemetry
service, hardware benchmark based on simulator speed, hosted SaaS, telemetry
collector, or cloud-account requirement. It cannot currently submit work to a
physical QPU.

## Current capabilities

VariaQ 0.5 supports domain-neutral optimization problem families:
VariaQ 0.7 supports domain-neutral optimization problem families:

- **MaxCut** — weighted graph partitioning into two sets.
- **Assignment** — tasks/resources with scores, costs, capacities, demands, and
Expand All @@ -54,7 +54,7 @@ support:
depends on the installed quantum backend and the binary-variable budget (see
`variaq capabilities --json`).
- **Graph Partitioning**: BQM lowering is implemented and tested, but quantum
support is experimental and not advertised for 0.5.0.
support is experimental and not advertised for 0.7.0.

Solvers:

Expand Down Expand Up @@ -125,9 +125,21 @@ Choose the smallest installation needed:
python -m pip install -e . # exact and heuristic
python -m pip install -e '.[quantum]' # add Qiskit
python -m pip install -e '.[cudaq]' # add CUDA-Q
python -m pip install -e '.[web]' # add the optional local web UI
python -m pip install -e '.[dev,quantum,cudaq]'
```

### Web UI (optional)

```bash
python -m pip install -e '.[web]'
variaq web
```

Then open <http://127.0.0.1:8701>. The UI is local-first and loopback-only by
default; see [docs/web-ui.md](docs/web-ui.md) for the security model, campaign
workflow, and API.

Python 3.12 or newer is required. CUDA-Q remains bounded to
`>=0.16,<0.17` because upstream `observe` and `sample` interfaces are
changing; the adapter must be reverified before widening the bound. CUDA-Q may
Expand Down
31 changes: 18 additions & 13 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ These are directions, not implemented features or delivery commitments.
quantum solvers;
- capability matrix derived from solver `supported_families` declarations.

## v0.6 — analysis, reporting, and scaling (in progress)
## v0.6 — analysis, reporting, and scaling (completed in 0.6.0)

- domain-neutral `ExperimentCampaign` definitions with deterministic IDs;
- bounded local campaign runner with default run-count guard and failure isolation;
Expand All @@ -73,20 +73,25 @@ These are directions, not implemented features or delivery commitments.
- JSON, CSV, and Markdown report exports;
- optional matplotlib plot generation from analysis data.

## v0.7 and later — heterogeneous execution, physical QPU exploration, and adapters
## v0.7 — local web UI (completed scope)

- explicitly authorized physical QPU execution;
- heterogeneous resources, optional remote workers, HPC/Slurm exploration,
optional server/API mode, and optional web UI.
- optional local-first web interface over a shared application service layer;
- versioned local JSON API (`/api/v1/`) with loopback-only default binding;
- dashboard, problems, runs, campaigns, analysis, reports, and capabilities pages;
- campaign plan-before-run workflow preserving the existing max-run guard;
- in-process sequential campaign execution with status/progress (no worker queue);
- analysis-visualization charts driven by structured `AnalysisResult` data;
- safe report downloads confined to known report artifacts.

## v0.8 and later — later exploration

Future candidates after 0.7 (none committed): richer interactive charts on the
existing API, campaign execution progress refinement, stronger classical
baselines evaluated only where they add scientific value, Graph Partition
quantum research, and optional authenticated LAN mode for trusted labs.
Physical-QPU execution, remote workers, and cloud hosting remain out of scope
pending explicit future design.

Possible external applications include cybersecurity, AI-agent scheduling,
logistics, graph optimization, scientific computing, and materials research.
They should use adapters rather than define VariaQ core.

## Recommended next milestone: 0.7 local web UI

The 0.6 analysis/reporting layer provides a clean backend for visualization.
A natural next milestone is a local web UI that consumes reports and campaigns
without moving scientific logic into the frontend. Another candidate is stronger
classical optimization baselines, evaluated only where they add clear scientific
value.
80 changes: 80 additions & 0 deletions docs/releases/v0.7.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# VariaQ 0.7.0 — Local Web UI

Release date: TBD (release-hardening complete).

## Highlights

- Optional local web interface: install with `pip install 'variaq[web]'` and
start with `variaq web`.
- Shared `VariaQService` application layer and a versioned local JSON API under
`/api/v1/`.
- Dashboard, problem/run/campaign detail, campaign planning and bounded
execution, analysis charts with data tables, reports, and capabilities views.
- Safe report downloads limited to known report artifacts beneath the configured
report root.
- Packaged Jinja templates, CSS, vanilla JavaScript, and vendored Chart.js; Node
is not required at runtime.

## Local startup and data roots

The default server address is <http://127.0.0.1:8701>:

```bash
variaq web
```

Existing local datasets can be selected explicitly:

```bash
variaq --db /path/to/variaq.sqlite3 --problems-dir /path/to/problems \
web --reports-dir /path/to/reports
```

The UI is local-first and has no authentication or internet-hardening claim.
Binding to a non-loopback address prints a prominent warning; use that only on
a trusted LAN and do not expose this server to the public internet.

## Campaign and report workflow

Campaign creation is plan-first. The plan displays the family, problem count,
requested run count, solver breakdown, unavailable combinations, warnings, and
the default 500-run limit before execution. Over-limit execution requires an
explicit acknowledgement and still passes through VariaQ's own max-run guard.
Execution is local, sequential, and limited to one campaign per server process.

Campaign analysis is calculated by VariaQ, not JavaScript. Charts consume the
structured analysis result and retain tabular text alternatives. Report pages
show report/campaign provenance, source-run counts, formats, and constrained
artifact downloads.

## Scientific presentation

Run pages keep decoded objective, optimized expectation, and lowered BQM energy
as distinct labeled quantities. Feasible and infeasible sample counts are shown
separately and do not determine run status. Quality and gap calculations remain
objective-sense aware in the Python analysis layer.

## Compatibility and packaging

- Python 3.12 or newer.
- Existing schema-version-`1` experiment databases remain compatible.
- The base installation does not require FastAPI, Jinja2, or Uvicorn.
- Linux and Windows CI exercise the web/API test suite; CUDA-Q, a GPU, and a
physical QPU are not required.
- The wheel contains all templates and static assets needed by the installed
server.

## Known limitations

- Task progress is in memory. If the server stops during a campaign, recorded
runs remain durable but the progress entry is lost.
- There are no accounts, collaboration features, remote workers, or remote
quantum providers.
- Charts currently cover campaign scaling analysis only.
- The UI is a local research interface, not a hardened multi-user web service.

## Explicit non-goals

No Triagewall integration, Ollama Fleet integration, bb scheduling logic,
physical-QPU execution, remote quantum provider, or `bb-plugin-variaq` change is
part of this release.
71 changes: 71 additions & 0 deletions docs/web-ui-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Web UI architecture decision (VariaQ 0.7.0)

## Chosen architecture

**FastAPI (backend) + Jinja2 server-rendered templates + vanilla JavaScript + Chart.js (vendored).**

- One ASGI app (`variaq.web.app`) serves both the versioned JSON API (`/api/v1/`)
and HTML pages.
- HTML pages are server-rendered Jinja2 templates; lightweight vanilla JS fetches
structured JSON from the same origin for dynamic tables, charts, and forms.
- Chart.js is vendored as a single static file. No Node.js, bundler, or frontend
build step exists at runtime or for contributors.
- The web layer talks to a shared application/service module
(`variaq.services`) which wraps the existing VariaQ subsystems. The browser
never touches SQLite directly and never computes scientific metrics.

## Why

| Requirement | How this stack meets it |
|---|---|
| Python backend integrates naturally with VariaQ | FastAPI is pure Python; services import VariaQ modules directly. |
| Optional dependency from base VariaQ | `[web]` extra only: fastapi, uvicorn, jinja2, python-multipart. Base install unchanged. |
| Minimal toolchain complexity | No Node/npm/Vite. Templates + static files shipped in the wheel. |
| Responsive research dashboard | Server-rendered HTML + CSS grid/flex; JS only for charts and async updates. |
| Charts/tables manageable | Chart.js consumes structured `AnalysisResult` JSON; tables render from bounded list endpoints. |
| Testable | FastAPI's `TestClient` (httpx) exercises API and HTML without a browser. |
| Maintainable by outside contributors | Plain Python + HTML/CSS/JS; no transpilation or framework lock-in beyond FastAPI/Jinja. |
| Local-first, safe defaults | FastAPI/uvicorn bind to 127.0.0.1 by default; warning on non-loopback. |

## Alternatives considered

**B. FastAPI + React/Vite.** Rejected for 0.7.0: introduces Node.js as a build
prerequisite, a compiled-frontend packaging problem, TypeScript codegen pressure,
and a large amount of tooling for an interface whose interactivity needs
(tables, forms, a handful of charts) are modest. The milestone explicitly
prefers avoiding a large frontend build system unless it materially improves
the product; it does not here. The API boundary being established means a
compiled SPA can be added later without changing the backend.

**C. NiceGUI / Reflex / Panel / Streamlit.** Rejected: these couple UI widgets to
Python objects, which invites business logic into the presentation layer and
makes the clean API boundary (needed for future integrations) harder to keep
honest. Streamlit in particular is multi-document-unfriendly and has weak
control over information density and navigation structure.

**D. HTMX-heavy partial-page swaps.** Considered as a variant of the chosen
stack. A small amount of fetch-based JS was judged simpler than introducing an
HTMX dependency for the handful of dynamic regions; charts need real JS anyway.

## Packaging implications

- `templates/` and `static/` live inside `src/variaq/web/` and are included in
the wheel via hatchling package data. Running the UI requires only
`pip install 'variaq[web]'`.
- No `node_modules`, source maps, or dev-server files are shipped.
- Base install (no `[web]`) remains dependency-free of FastAPI/uvicorn/Jinja2;
`variaq web` prints an actionable install hint rather than a traceback.

## Development workflow

pip install -e ".[web,dev]"
variaq web # serves http://127.0.0.1:8701
pytest tests/web # API + template tests, no browser needed

## Future extension path

- The `/api/v1/` contract is the stable boundary: a React/Vite SPA, a TUI, or
third-party integrations can consume it without touching server code.
- Campaign task tracking is intentionally in-process and single-flight; a richer
progress model can be added behind the same `/api/v1/campaigns/tasks/`
endpoints without breaking the UI.
Loading
Loading