Skip to content
@vista-forge

VistA Forge

The hardened, industry-standard VistA/M toochain

VistA Forge

The hardened, industry-standard VistA/M toolchain

Status Engines Built with

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.

Hardened. Industry-standard.

The tagline makes two claims, and both are load-bearing — they are the standout features of VistA Forge.

Hardened — the VistA layer. VistA Forge treats VistA the way regulated industries treat production software:

  • 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, never a convention or a review note.
  • TDD for every VSL module. Each VSL* module is built test-first against live VistA, with per-module coverage gates.
  • TDD for every v-app. Each Go client is built the same way — unit tests, golden tests, and drift gates on its generated bindings.
  • Full-corpus, live-system testing. VSL suites and executable examples run in CI against two complete live VistA systems — YottaDB and IRIS — each carrying VistA's full ~40k-routine base; the KIDS lifecycle is proven against a 2,404-distribution corpus with byte-identical round-trips.
  • Provable reversibility. A release tag can only exist after a full build → install → verify → test-on-installed → uninstall cycle diffs byte-clean against baseline on both engines, and every engine mutation lands in a hash-chained attestation ledger.
  • Declared data ownership. Modules declare their file footprints (@file <n> <mode>), exactly one module may write a given file, and every mutating verb carries fail-closed, host-attributed audit.

Industry-standard — the M layer. The same tooling every mainstream language takes for granted, built on the M standard itself:

  • One grammar, from the M standard. tree-sitter-m is built against the M standard as implemented across today's M systems — and drives the first real formatter, linter, and LSP language server M has ever had, all on one shared parser.
  • The M Standard Library (MSL). 40 STD* modules make M a peer of every modern mainstream language for 2026-era development — JSON, HTTP(S), JWT, crypto digests, UUIDs, base64, regex, S3, testing, and more — conformance-tested against vendored RFC/NIST corpuses, identical on both engines.
  • Mainstream delivery. Git-canonical .m source, static Go binaries, Docker engines, and CI on every push.

By the numbers (measured from the repos, July 2026):

Hardening surface Measure
M unit tests — MSL + VSL (incl. VWEB) 64 suites · 1,400+ test cases · 3,200+ assertions, every suite run on both engines
Go unit tests — toolchain + v-apps 1,300+ test functions (665 m-layer, 667 v-apps), table-driven
Executable doc examples — MSL + VSL 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 + an engine-access scan in every M CI caller + a scheduled org-wide meta-gate backstop
m-engine waterline checks an executable conformance gate per driver (m-ydb, m-iris) — 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

And the gating is rigid top to bottom: a red anywhere is a hard stop — it blocks the commit, the merge, or the release tag. Nothing in the stack ships around a failing gate.

Contents

The stack at a glance

The VistA layer (v-*, top table) is built from one repeating shape — a v-app, where app is a VistA functional domain (package management, database management, task management, …). Each domain ships as a client and a server component joined by a client-server API, consolidating an entire category of VistA-specific functionality into one coherent command-line (or web) interface the end user actually drives. Beneath it, the engine-neutral M layer (m-*, bottom table) is the toolchain, seam, and runtime every domain is built on.

The two are split by the v/m waterline — dependency is one-way, v → m, never back — and each italic (gray) row is itself an enforced seam, held by a generated registry and a red gate rather than convention.

VistA-specific (v-*)

Layer What it is & does
v-app end-user client application (written in Go) for a v-stdlib domain (database, tasks, monitoring, …), using a modern, mainstream user interface and naming conventions, with comprehensive quality, safety, and unit tests — VistA-specific terminology and syntax modernized to mainstream terms
v-api client-server API — carries every client-to-server verb call, audited
v-stdlib VistA Standard Library (VSL). A library comprised of wrappers of VistA infrastructure applications (FileMan, Kernel, …) using modern, mainstream formats, naming conventions, and APIs

M-general — engine-neutral (m-*)

Layer What it is & does
m-toolchain m dev tools — fmt · lint · lsp · test · coverage, one shared parser
m-stdlib M Standard Library (MSL). A portable, industry-standard M library of 40 STD* runtime modules (JSON, HTTP, crypto, testing, …)
m-driver-sdk M engine seam — the only path to a live engine
m engines YottaDB / IRIS — run VistA; vendor specifics contained in the drivers (m-ydb, m-iris)

The two standard libraries this stack is built on:

  • VSL — the VistA Standard Library. A thin wrapper around VistA's bespoke technology (Kernel, FileMan, KIDS), reframed in modern mainstream terms and methods — so working against VistA feels like working against an ordinary, well-typed API.
  • MSL — the M Standard Library. A suite of industry-standard libraries (JSON, HTTP, crypto, testing, dates, and more) that make M a peer of other mainstream languages instead of a special case.

Each layer is a repo family covered below; how the three seams are generated and red-gated is in Architecture.

Why VistA Forge

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. The everyday developer loop every modern language takes for granted has simply never existed for M.

VistA Forge closes that gap — not by rewriting VistA, but by building the modern loop around it:

  • Git-canonical source.m files under version control; the database is the runtime, not the repository.
  • Real editor tooling — formatter, linter, and language server, all on one shared parser.
  • Test-first against live engines — unit tests and coverage gates run on real YottaDB and IRIS instances, in CI, on every push.
  • Patches as code — KIDS distributions decomposed into git-diffable trees, built from drift-gated specs, provably reversible.
  • Agent-ready by construction — one command grammar and reflected schemas expose the whole toolchain to AI agents over MCP.

And because the m-* half is engine-neutral, none of it is VistA-bound: the same toolchain works on any M system, in healthcare and beyond.

Start here

  • Want the tool? m-cli is the m command; its README has install + first-run instructions.
  • Want a running VistA? docker pull ghcr.io/vista-forge/vista-iris:latest boots a fully installed VistA-on-IRIS with fictitious test data.
  • Setting up a machine? workspace./bootstrap.sh clones every repo and generates the Go workspace.
  • Want the design record? The docs repo holds the ADRs and design corpus behind everything below.

What's here, by developer task

Write M like any modern language

m fmt (AST-preserving formatter), m lint (query-driven rule engine, with XINDEX/VistA-Kernel compatibility profiles), and m lsp (an LSP 3.x language server) all sit on one parserm-parse, which embeds the tree-sitter-m grammar as WASM and runs it through wazero. The whole toolchain ships as static Go binaries with no CGO and 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 this org is built test-first and gated on both engines.

Stop hand-rolling utilities — the M standard library

m-stdlib (tagged through v0.13.0) is a pure-M library of 40 STD* modules: data formats (STDJSON, STDXML, STDTOML, STDCSV, STDREGEX, STDURL), encoding (STDB64, STDHEX, STDUUID), testing (STDASSERT, STDMOCK, STDFIX, STDSEED, STDSNAP, STDPROF), crypto and auth (STDCRYPTO, STDCSPRNG, STDJWT, STDSIGV4), networking (STDHTTP, STDHTTPD, STDNET, STDS3), plus dates, logging, collections, strings, math, filesystem, and more. Conformance-tested against vendored RFC/NIST corpuses; identical on YottaDB and IRIS.

Reach an engine exactly one way

m-driver-sdk defines the vendor-neutral driver contract — typed verbs (Health · Load · Exec · ReadGlobal · SetGlobal), a structured engine-error model, honest capability documents, and an executable conformance gate that any driver binary must pass. Two drivers implement it today:

  • m-ydb — YottaDB, over local, Docker, and SSH transports, plus native passthrough to the full YottaDB utility surface (mupip, dse, gde, …).
  • m-iris — IRIS, over Atelier REST (remote), Docker session, and local transports, including routine sync/deploy into an IRIS namespace.

Everything above the seam — m test, m vista exec, the v tools — reaches an engine only through this contract. Both drivers are conformance-green and proven against live VistA systems on their respective engines.

Treat VistA patches as code

v-pkg (tagged through v0.6.1) 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; build from a drift-gated spec; install, verify, and cleanly back out against a live engine. Mounted as v pkg on the v-cli umbrella.

Build VistA-side libraries on tested seams

v-stdlib (released as VSL*1.0*24 / tag v1.0.24) is the VistA Standard Library — VSL* modules wrapping Kernel/FileMan seams behind tested M APIs: VSLCFG (XPAR configuration), VSLSEC (Kernel security), VSLFS (FileMan file storage), VSLIO (file I/O), VSLLOG (audit logging), VSLTASK (TaskMan) — plus the VSLAPI admin-verb dispatcher and its VSLPING diagnostic prover (next section). Every label carries machine-read source tags (@publish, @mutates, @since, @file <n> <mode>, @call) that generate the VSL manifest — the registry every downstream surface is built from. Ships as a single deterministic KIDS build, exercised against live VistA on both engines; a release tag can only be cut when the lifecycle-healthcheck gate proves the build byte-clean reversible (build → install → verify → suites-on-installed → uninstall → baseline diff) on both.

Administer VistA with plain-noun commands — VSL modules ⇄ v apps

The sysadmin platform pairs each engine-side VSL* module with a host-side v <domain> command, generated — not hand-wired — from the VSL manifest:

  • Engine half: a module opts its labels into dispatch (@dispatch); the gen cascade projects them into a generated verb table (VSLAPIT) that the VSLAPI dispatcher serves over a versioned JSON envelope (b64 request in, sentinel-framed reply out, typed error classes, pagination tokens, and fail-closed host-attributed audit for every mutating verb). VSLPING (echo/sum/page/fail/touch) is the platform prover.
  • Host half: v-base is the shared library every domain pins (like clikit and the driver SDK): the dispatch client, engine profiles (--engine vehu|foia), the pagination runtime, the --yes/exit-4 confirm conventions — and vslgen, which turns the pinned manifest into typed Go bindings plus a free explain command per verb (APIs wrapped, ICRs, files touched, safety class). A domain that drifts from its manifest fails CI, not code review.
  • The commands: plain nouns a developer can guess, mounted on the v-cli umbrella — v pkg (KIDS), v rpc-debug / v rpc-tap (Broker) today; the VSL-backed sysadmin set (v alert first, then v ping, v config/VSLCFG, v task/VSLTASK, v sec/VSLSEC, audit via VSLLOG, …) lands vertical-by-vertical as the platform build-out (B1–B2) completes. VA product names never appear in a command — a lint gate enforces the plain language.

Observe the RPC Broker

v-rpc-debug (tagged through v0.3.0, mounted as v rpc-debug) is a read-only RPC observation tool over the broker's native XWBDEBUG logging: doctor, arm/disarm, tail, capture, status, with LDJSON output for offline analysis — no modifications to the running system.

Run VistA on your own machine

vista-iris publishes a multi-arch container of WorldVistA on IRIS for Health Community — the full site build (routine/global import, FileMan/Kernel install) is baked into the image, so it boots already operational: Management Portal + REST (52773), RPC Broker for CPRS (9430), HL7 MLLP (5026), IRIS superserver (1972). Fictitious test data only.

Drive it all with an AI agent

Every binary shares one command grammar (clikit, tagged through v0.8.0): --output text|json|auto, a versioned JSON envelope, a deterministic exit-code ladder, and a reflected schema command — so an AI agent invokes the same gated surface a human uses and gets machine-parseable results. (An MCP shim over that schema was built and retired unused — m-dev-tools-mcp, archived 2026-07-05, kept read-only as the reference for the pattern.)


Architecture: enforced waterlines + registries

The org is partitioned by three hard boundaries, and every boundary is held by a generated registry with a red gate — never by convention or code review.

The m/v waterline splits everything on one question — does this code work on a bare M engine with no VistA installed?

  • m-* — the M standard toolchain: works on any M implementation, with or without VistA — VistA today, and equally the other M-based systems across healthcare and finance (Epic, MEDITECH, LabCorp, and others). Includes MSL, the STD* M standard library.
  • v-* — VistA-specific: needs Kernel/FileMan/KIDS. Includes VSL, the VSL* VistA standard library, and the v <domain> sysadmin apps.

Dependency is one-way — v → m, never the reverse.

The dispatch seam splits the v layer itself into an engine half (VSL* M modules + the VSLAPI dispatcher) and a host half (v-base + the v <domain> Go apps). The two halves share exactly one contract: the versioned VSLAPI envelope, whose verbs, parameter shapes, safety classes, and data footprints are all projections of one generated registry — the VSL manifest. Host bindings are generated from it (vslgen); the engine dispatch table is generated from it; a drift on either side is a CI failure.

The m-engine waterline separates everything above from the vendor-specific engines: the only path to a live engine is the m-driver-sdk contract (one Go client, one envelope), with all vendor specifics below it in the drivers (m-ydb, m-iris). Raw docker exec / direct-mode access is denied by tooling, not discouraged by docs.

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 (ICRs/DBIAs) recorded in prose nobody executes, naming policed by human SAC 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 dependency direction, G2 no VistA symbols below the line, G3 transport monopoly, G4 seam pin) + a scheduled bidirectional meta-gate
Engine access driver capability document + seam contract executable conformance gate per driver; engine-access scan red-gates any hand-rolled transport
Admin verbs vsl-manifest.json (from @publish/@since/@mutates tags) → generated VSLAPIT dispatch table + vslgen host bindings dispatch/bindings drift gates; G-compat — the published surface is additive-only against the last release tag
Data ownership per-module @file <n> <mode> footprints in the manifest G-data — source scan vs declared footprint, single-writer-per-file, classified-direct + sprawl counters
Module granularity manifest calls DAG + seam projections G-lateral (label granularity, no lateral tangles)
Releases deterministic KIDS build spec → dist/VSL.kids lifecycle-healthcheck: install → verify → suites-on-installed → uninstall → byte-clean baseline diff, both engines — a release tag may exist only on green; every engine 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)
Host frameworks pinned clikit / m-driver-sdk / v-base versions G-framework meta-gate — every domain pins the same versions

So no application "owns its own data" in the VistA sense: a VSL module declares which files it touches and how, exactly one module may write a given file, every mutating verb is audited with host attribution, and a patch that cannot prove byte-clean reversibility cannot become a release.

The stack

The layer stack itself is the table in The stack at a glance; here is what's inside each band.

Inside the v layer

The two halves share exactly one contract — the versioned VSLAPI envelope — and both sides of it are generated from the VSL manifest:

flowchart TB
    subgraph host["host half — Go, on your machine"]
        vcli["v CLI umbrella — v pkg · v rpc-debug · v rpc-tap · v alert …"]
        vbase["v-base — dispatch client · engine profiles · pagination · vslgen"]
        vcli --> vbase
    end
    subgraph eng["engine half — M, inside VistA"]
        vslapi["VSLAPI dispatcher + generated VSLAPIT verb table"]
        vsl["VSL* modules — VSLCFG · VSLSEC · VSLFS · VSLIO · VSLLOG · VSLTASK · VSLPING …"]
        data[("Kernel / FileMan / KIDS data — @file-declared, single-writer-per-file")]
        vslapi --> vsl --> data
    end
    manifest[["vsl-manifest.json — generated from @publish / @mutates / @file / @call tags"]]
    vbase -. "dispatch seam — versioned JSON envelope, audited mutations" .-> vslapi
    manifest -. "vslgen → typed Go bindings" .-> vbase
    manifest -. "→ VSLAPIT dispatch table" .-> vslapi
Loading

Inside the m layer

Editor tools sit on one shared parser and never need an engine; engine tools reach one only through the seam:

flowchart TB
    subgraph editor["editor and CI tools — no engine needed"]
        fmt["m fmt · m lint · m lsp"]
        parse["m-parse — one shared parser (tree-sitter-m as WASM)"]
        fmt --> parse
    end
    subgraph livetools["live-engine tools"]
        test["m test · m coverage · m vista exec · m arch"]
    end
    msl["MSL — the STD* M standard library (40 modules: JSON · HTTP · crypto · testing · …)"]
    seam["mdriver.Client — down through the engine seam"]
    test -- "runs *TST.m suites over" --> msl
    test --> seam
Loading

Below the seam

One contract, two conformance-gated drivers, all vendor specifics contained:

flowchart TB
    sdk["m-driver-sdk — typed verbs (Health · Load · Exec · ReadGlobal · SetGlobal) + executable conformance gate"]
    ydb["m-ydb — local · Docker · SSH transports, plus mupip/dse/gde passthrough"]
    iris["m-iris — Atelier REST · Docker · local transports, plus routine sync/deploy"]
    y[("YottaDB")]
    i[("InterSystems IRIS")]
    sdk --> ydb --> y
    sdk --> iris --> i
Loading

The repos

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.8.1
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

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- CLIs — VSLAPI dispatch client (envelope codec, engine profiles, pagination, attribution/--yes) + the vslgen binding generator (vista-sysadmin-base §5) v0.3.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

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 (ghcr.io/vista-forge/vista-iris), fictitious test data only
.github Reusable CI (go-ci, m-ci, arch-waterline, docs-validate), the docs standard (CONVENTIONS.md), the org repo registry, and the scheduled meta-gate

Design principles

  • Git-canonical source. M code lives in .m files 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-sdk contract — no hand-rolled transports, verified by an executable conformance gate.
  • Gated, not aspirational. The layer boundaries, seam contracts, registries, KIDS build specs, and doc links are all generated, drift-gated artifacts checked in CI — not conventions enforced by review. A new layer earns trust by adding its source-tag → generate → registry → red-gate triple.
  • Declared data ownership. A module states which VistA files it touches and how (@file <n> <mode>); a source scan red-gates undeclared access, and exactly one module may write a given file — the inverse of VistA's everyone-writes-everything coupling.
  • 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 against baseline on both engines.
  • Static, dependency-free binaries. CGO_ENABLED=0 everywhere; even the M parser runs as WASM.
  • One contract, many surfaces. A single command grammar and reflected schema mean CLI flags, JSON envelopes, and MCP tools never drift.
  • Test-first. Every module is built TDD with per-module coverage gates; m-stdlib conformance suites run against vendored RFC/NIST corpuses.

Contributing

Contributions are welcome. The org-wide guides live in this .github repo:

The toolchain is Apache-2.0 org-wide (relicensed 2026-07-03) — see each repo's LICENSE/NOTICE. The two documented exceptions are the MIT VS Code extensions and the embedded tree-sitter-m grammar in m-parse, whose upstream (in the separate m-dev-tools org) is still AGPL-3.0 pending relicense.

Not affiliated with or endorsed by the US Department of Veterans Affairs. "VistA" refers to the public-domain VA health information system. These tools operate on VistA source and ship with fictitious test data only — never load real patient (PHI/PII) data into instances used with them.


Shared CI

Go repos call the reusable workflows in this repo:

uses: vista-forge/.github/.github/workflows/go-ci.yml@main

Popular repositories Loading

  1. m-standard m-standard Public

    M Standard

    Python 1

  2. tree-sitter-m tree-sitter-m Public

    M Language Parser

    JavaScript 1

  3. vista-atlas vista-atlas Public

    Vista Atlas — VSCode extension over the vdocs gold-corpus release: what the VA documentation SAYS. Twin of vista-compass.

    TypeScript 1

  4. vista-compass vista-compass Public

    Vista Compass — VSCode extension over the vista-meta data release (meta.db): what the VistA system measurably IS. Twin of vista-atlas.

    TypeScript 1

  5. m-modern-corpus m-modern-corpus Public

    Snapshot collection of modern (non-VistA) M source for tooling validation — companion to m-cli and tree-sitter-m

    M

  6. doc-framework doc-framework Public archive

    Python

Repositories

Showing 8 of 8 repositories

People

This organization has no public members. You must be a member to see who’s a part of this organization.

Top languages

Loading…

Most used topics

Loading…