VistA Forge
The hardened, industry-standard VistA/M toolchain.
Work on VistA like it's 2026, not 1985. VistA Forge gives M the
developer experience every other language takes for granted: format and lint in your
editor, navigate over a real language server, run unit tests with coverage against a
live engine on every push, call a 40-module standard library instead of
hand-rolling utilities, and ship VistA patches that provably install — and provably back
out. Your code lives in git; the M engine is just the runtime. One
docker pull gets you a running VistA; one static binary gets you the whole
toolchain — identical on YottaDB and InterSystems IRIS.
docker pull ghcr.io/vista-forge/vista-iris:latest
A fully installed VistA-on-IRIS, public and pullable today. The toolchain repos are opening as they stabilize — see what's available now.
Hardened. Industry-standard.
The tagline makes two claims, and both are load-bearing.
VistA — the VA's public-domain hospital information system — has run real hospitals for over four decades and is one of the largest working bodies of M (MUMPS) code in existence. Yet developing on it today still means working the way its authors did in the 1980s: code lives in the database rather than in git; there is no formatter, no linter, no language server, no unit-test runner, no coverage, no CI; and a patch installs into a live system with no reliable way to back it out. VistA Forge closes that gap — not by rewriting VistA, but by building the modern loop around it.
Hardened — the VistA layer
VistA, treated the way regulated industries treat production software
Nothing here is enforced by convention or a review note. Every boundary is a generated registry held by a red gate.
- Contract/registry-based seams. Every cross-layer boundary — the m/v waterline, the client-server dispatch seam, the engine seam — is a generated registry held by a red gate.
- TDD for every module. Each
VSL*module is built test-first against live VistA, with per-module coverage gates; each Go client the same way. - Full-corpus, live-system testing. Suites and executable examples run in CI against two complete live VistA systems, each carrying VistA's full ~40k-routine base.
- Provable reversibility. A release tag can only exist after a build → install → verify → test → uninstall cycle diffs byte-clean against baseline on both engines.
- Declared data ownership. Modules declare their file footprints, exactly one module may write a given file, and every mutating verb carries fail-closed, host-attributed audit.
Industry-standard — the M layer
The tooling every mainstream language takes for granted, built on the M standard itself
And because the m-* half is engine-neutral, none of it is VistA-bound — the same toolchain works on any M system.
- The M standard, machine-readable.
m-standardreconciles the Annotated M Standard, YottaDB, IRIS, and the VA's SAC/XINDEX rules into one citable reference that parsers, linters, and AI agents consume directly. - One grammar, generated from that standard. tree-sitter-m parses the full ~39k-routine VistA corpus at over 99% clean and stamps every token with its portability tier — driving the first real formatter, linter, and LSP server M has ever had.
- Validated beyond VistA.
m-modern-corpussnapshots ~4,000 routines of modern open-source M as a second validation corpus — proving the rules hold on today's idioms, not just VA legacy style. - The M Standard Library. 40
STD*modules — JSON, HTTP(S), JWT, crypto, UUIDs, regex, S3, testing — conformance-tested against vendored RFC/NIST corpuses, identical on both engines. - Mainstream delivery. Git-canonical
.msource, static Go binaries, Docker engines, and CI on every push.
By the numbers
A red anywhere is a hard stop.
Measured from the repos, July 2026. The gating is rigid top to bottom — it blocks the commit, the merge, or the release tag. Nothing in the stack ships around a failing gate.
--error-on=error| Hardening surface | Measure |
|---|---|
| M unit tests (MSL + VSL) | 64 suites · 1,400+ test cases · 3,200+ assertions, every suite run on both engines |
| Go unit tests (m-apps + v-apps) | 1,300+ test functions (665 m-layer, 667 v-apps), table-driven |
| Executable doc examples | 51 generated example programs from 500+ @example tags, run against the live VistA engines |
| CI coverage | 21 repos gated on every push; 15 layer-bearing repos each run the waterline gates |
| m/v waterline checks | G1–G4 (m arch check: dependency direction, no VistA symbols below the line, transport monopoly, seam pin) in every layer-bearing repo's CI, plus a scheduled org-wide meta-gate backstop |
| m-engine waterline checks | an executable conformance gate per driver — a driver binary that can't pass it can't ship |
| VSL drift gates | 24 red gates in one make gates run — ICR, namespace, engine-access, manifest/dispatcher/envelope drift, data ownership, additive-only compat |
| Hard stops | lint --error-on=error zero findings · ≥85% per-module coverage · release only on a byte-clean lifecycle, both engines |
The stack at a glance
Two layers, split by an enforced waterline.
The VistA layer (v-*) is built from one repeating shape — a
v-app, where app is a VistA functional domain. Each domain ships as a
client and a server joined by a client-server API, consolidating an entire category of
VistA-specific functionality into one interface the end user actually drives. The
M layer (m-*) is the engine toolchain, seam, and runtime every
domain is built on. Each seam row is itself an enforced contract, held by a generated
registry and a red gate rather than convention.
m dev tools — fmt · lint · lsp · test · coverage — all on one shared parser.STD* runtime modules — JSON, HTTP, crypto, testing, and more.What's here, by developer task
The everyday loop M never had.
Write M like any modern language
m fmt (AST-preserving formatter), m lint (query-driven rule
engine, with XINDEX/Kernel compatibility profiles), and m lsp (an LSP 3.x
language server) all sit on one parser — m-parse, which
embeds the tree-sitter-m
grammar as WASM and runs it through wazero. Static Go binaries, no CGO, no C toolchain at
runtime.
Test against a real engine, with coverage
m test runs *TST.m suites on a live YottaDB or IRIS engine via
^STDASSERT, with machine-readable results; m coverage produces
LCOV with per-module coverage gates. Every library in the org is built test-first and
gated on both engines.
Stop hand-rolling utilities
m-stdlib is a pure-M library of 40 STD* modules:
data formats (STDJSON, STDXML, STDCSV,
STDREGEX), encoding, testing (STDASSERT, STDMOCK),
crypto and auth (STDCRYPTO, STDJWT), networking
(STDHTTP, STDS3), plus dates, logging, collections, strings,
math, and filesystem.
Reach an engine exactly one way
m-driver-sdk defines the vendor-neutral driver contract — typed verbs, a
structured engine-error model, honest capability documents, and an executable
conformance gate any driver binary must pass. Everything above the seam reaches
an engine only through this contract.
Treat VistA patches as code
v-pkg gives KIDS — VistA's native package/patch format — a
real lifecycle: parse, classify, lint, decompose, assemble, roundtrip, diff, build,
install, verify, snapshot, restore, uninstall, attest. Decompose a distribution into a
git-diffable component tree and reassemble it byte-identically; install, verify, and
cleanly back out against a live engine.
Administer VistA with plain-noun commands
The sysadmin platform pairs each engine-side VSL* module with a host-side
v <domain> command, generated — not hand-wired — from
the VSL manifest. Plain nouns a developer can guess: v pkg,
v rpc-debug, v rpc-tap. VA product names never appear in a
command; a lint gate enforces the plain language.
Run VistA on your own machine
vista-iris publishes a multi-arch container of WorldVistA on IRIS for Health Community — the full site build is baked into the image, so it boots already operational: Management Portal and REST, RPC Broker for CPRS, HL7 MLLP, IRIS superserver. Fictitious test data only.
Drive it all with an AI agent
Every binary shares one command grammar (clikit):
--output text|json|auto, a versioned JSON envelope, a deterministic exit-code
ladder, and a reflected schema command — so an agent invokes the same gated
surface a human uses and gets machine-parseable results.
Architecture
Why registries — VistA's failure mode, inverted.
Classic VistA integrates by reaching into other packages' globals: every
application owns its own data and freely reads and writes everyone else's, with the
agreements recorded in prose nobody executes, naming policed by human review, and patches
installed with no reliable back-out. The result is the coupling archaeology every VistA
developer knows. Here the same concerns are declared, generated, and red-gated
— one discipline, source-tag → generate → registry → red-gate, at every layer.
| Surface | Registry (generated) | Red gate |
|---|---|---|
| Repo layering | ecosystem.json — layer per repo |
arch-waterline in every repo's CI (G1–G4), plus a scheduled bidirectional meta-gate |
| Engine access | driver capability document + seam contract | executable conformance gate per driver; an engine-access scan red-gates any hand-rolled transport |
| Admin verbs | vsl-manifest.json → generated dispatch table + host bindings |
dispatch/bindings drift gates; the published surface is additive-only against the last release tag |
| Data ownership | per-module @file <n> <mode> footprints in the manifest |
source scan vs declared footprint, single-writer-per-file, sprawl counters |
| Releases | deterministic KIDS build spec → dist/VSL.kids |
lifecycle-healthcheck: install → verify → suites → uninstall → byte-clean baseline diff, both engines. Every mutation lands in a hash-chained attestation ledger. |
| Command surface | v-registry.json — the v umbrella mounts |
registry golden test + plain-language lint (no VA product names in commands) |
docker exec and
direct-mode engine access are denied by tooling, not discouraged by docs.
The repos
Everything in the org.
The toolchain is in active development and most of it is still private while the seams and licensing settle. Linked names are public today; the rest are listed for shape and open as they land.
docker pull ghcr.io/vista-forge/vista-iris:latest) — a fully
installed VistA-on-IRIS with fictitious test data. The
tree-sitter-m grammar — a real
parser for M. And the twin editor extensions,
vista-atlas and
vista-compass.
M toolchain — engine-neutral
| Repo | Delivers | Latest |
|---|---|---|
| m-cli | Cross-engine M toolchain — the m busybox (fmt/lint/lsp/test/coverage/watch/vista/arch) | v0.1.0 |
| m-stdlib | Pure-M runtime standard library — STD* modules | v0.13.0 |
| m-driver-sdk | M engine-driver SDK — the seam contract + reference engine Client (mdriver.Client) | v0.11.0 |
| m-ydb | YottaDB engine driver — the m-ydb binary producing the driver envelope | — |
| m-iris | InterSystems IRIS engine driver — the m-iris binary producing the driver envelope | v0.1.0 |
| m-parse | Engine-neutral M parse substrate — tree-sitter-m over wazero; the foundation fmt/lint/lsp sit on (spec §4) | v0.1.0 |
| clikit | Shared CLI convention layer — Kong grammar, JSON envelope, exit-code ladder — for the m-* / v-* Go toolchain (engine-neutral; no engine transport) | v0.9.0 |
VistA toolchain — requires Kernel / FileMan / KIDS
| Repo | Delivers | Latest |
|---|---|---|
| v-pkg | VistA KIDS packaging — the v pkg domain (build/install/verify/uninstall over the m engine seam) | v0.7.0 |
| v-cli | The v CLI umbrella — VistA developer tooling (v pkg/db/config/…) aggregated under one binary | — |
| v-stdlib | VistA Standard Library — VSL* routines (VistA-specific; consumes the engine-neutral STD* base upward) | v1.0.25 |
| v-base | Host base library for v-<domain> CLIs — VSLAPI dispatch client (envelope codec, engine profiles, pagination, attribution/--yes) + the vslgen binding generator (vista-sysadmin-base §5) | v0.4.0 |
| v-db | VistA FileMan data-dictionary / PIKS profiler — the v db domain (read-only inspect/profile over the m engine seam via v-base) | — |
| v-web | VistA Web Services — VWEB* routines: the inbound socket adapter (listener + device/TLS adapter) that drives the m-stdlib STDHTTPD server framework over a real socket | — |
| v-rpc-debug | VistA RPC developer tools — the v rpc-debug domain | v0.4.0 |
| v-rpc-tap | VistA scalable RPC tap — the v rpc-tap domain | — |
The M standard & corpora
| Repo | Delivers |
|---|---|
| tree-sitter-m | The M grammar — generated from m-standard's data; parses the full VistA corpus at over 99% clean |
| m-standard | The M standard, machine-readable — the Annotated M Standard, YottaDB, IRIS, and VA SAC/XINDEX rules reconciled into one citable reference |
| m-modern-corpus | ~4,000 routines of modern open-source M (EWD, the YottaDB web server, mgsql, YDBOcto) as a second validation corpus |
Editor extensions
| Repo | Delivers |
|---|---|
| vista-atlas | VS Code extension over the vdocs gold-corpus release — what the VA documentation says. Twin of vista-compass. |
| vista-compass | VS Code extension over the vista-meta data release — what the VistA system measurably is. Twin of vista-atlas. |
Shared foundations & infrastructure
| Repo | Delivers |
|---|---|
| go-cli-template | Scaffold for new Go CLIs in the house style (carries the canonical, drift-gated .golangci.yml) |
| docs | ADRs, design corpus, and cross-repo coordination |
| workspace | Clone-all manifest + idempotent bootstrap.sh for machine setup |
| vista-iris | Pre-built VistA-on-IRIS container, fictitious test data only — the image is public; the build repo is not yet |
| .github | Reusable CI, the docs standard, the org repo registry, and the scheduled meta-gate |
Design principles
What the whole stack agrees on.
- Git-canonical source. M code lives in
.mfiles under version control; the database is the runtime, not the repository. - Dual-engine parity. YottaDB and IRIS are both first-class; the same suites gate both, and engine specifics live only inside the drivers.
- One seam. Every tool reaches a live engine through the
m-driver-sdkcontract — no hand-rolled transports, verified by an executable conformance gate. - Gated, not aspirational. Layer boundaries, seam contracts, registries, build specs, and doc links are generated, drift-gated artifacts checked in CI — not conventions enforced by review.
- Declared data ownership. A module states which VistA files it touches and how; a source scan red-gates undeclared access, and exactly one module may write a given file.
- Reversible by proof. Engine mutations are audited into a hash-chained attestation ledger, installs capture pre-images, and a release tag can only be cut when a full install → uninstall cycle diffs byte-clean.
- Static, dependency-free binaries.
CGO_ENABLED=0everywhere; even the M parser runs as WASM. - One contract, many surfaces. A single command grammar and reflected schema mean CLI flags, JSON envelopes, and agent tools never drift.
- Test-first. Every module is built TDD with per-module coverage gates; conformance suites run against vendored RFC/NIST corpuses.
- Plain nouns. A command wraps an insider VistA subsystem in a name a developer can guess — and a lint gate keeps it that way.