From a2cbde3b532cba4fd210cde131cfc6966c179eea Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Mon, 15 Jun 2026 18:11:49 -0400 Subject: [PATCH 1/7] T1.2 groundwork: VSLCFG working design + engine/citation findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkpoint (no VSL* code yet). Captures the expensive-to-re-derive findings: - vehu (worldvista/vehu, GT.M V7.0-005) IS reachable via docker exec here, with live XPAR — the YDB-VistA test leg works from this sandbox (no IRIS-VistA up, so that leg is likely owed). - XPAR binding semantics probed live (entity "SYS" accepted; $$GET^XPAR/EN^XPAR; error codes; precedence via "ALL"; no $$ENT^XPAR). - Citation reconciled: @source XU/krn_8_0_dg_toolkit_ug (ICR #2263 Supported), correcting the plan's XT/ktk7_3p26sp guess. - Test-param + VSLCFG API design decisions. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/t1.2-vslcfg-design.md | 104 +++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/plans/t1.2-vslcfg-design.md diff --git a/docs/plans/t1.2-vslcfg-design.md b/docs/plans/t1.2-vslcfg-design.md new file mode 100644 index 0000000..5040d08 --- /dev/null +++ b/docs/plans/t1.2-vslcfg-design.md @@ -0,0 +1,104 @@ +--- +title: "T1.2 — VSLCFG adapter: working design + engine findings" +status: in-progress +created: 2026-06-15 +doc_type: [PLAN] +plan: ../../../docs/vsl-msl/vsl-implementation-plan.md (T1.2 row) +kickoff: ../../../docs/prompts/t1.2-vslcfg-kickoff.md +--- + +# T1.2 — `VSLCFG` adapter (bind `STDENV` config-read seam → XPAR) + +Working design + the engine/citation groundwork established at session start. +Branch `t1.2-vslcfg`. This note captures the expensive-to-re-derive findings so +continuation doesn't repeat the discovery. + +## Established (session 1 groundwork) + +### Engine — the YDB-VistA leg IS reachable from this sandbox +- **`docker exec vehu …` WORKS here** (contrary to the older "docker-exec + blocked / live run owed to user" notes — that was a prior sandbox state). + `vehu` = `worldvista/vehu`, **GT.M V7.0-005**, running, with live + Kernel/FileMan/**XPAR**. +- Run raw M on vehu: + `docker exec -i vehu bash -lc '. /home/vehu/etc/env; $gtm_dist/mumps -direct'` + (`$gtm_dist=/home/vehu/lib/gtm`). Always set `S DUZ=1,DUZ(0)="@",U="^",DT=$$DT^XLFDT` + first (full FM priv + the `U="^"` that several VistA APIs assume). +- `GET^XPAR` and `EN^XPAR` both exist on vehu; `$$DT^XLFDT` works. +- **GT.M direct-mode caveat:** argumentless-`DO` dot-blocks do NOT work when fed + line-by-line over a heredoc (each line parses independently → `Command + expected`). Use single-line `FOR`/compound lines, or stage a routine and call it. +- **No IRIS-VistA (`foia`) container is currently running** (only the bare + `m-test-iris`; the shared `vista-iris` is OFF-LIMITS). So the **IRIS leg of + "green both engines" is likely OWED** until a VistA-on-IRIS instance is up — + mirror of how T0.1's YDB live run was owed. Develop YDB-green first. + +### XPAR binding semantics (probed live on vehu) +- `EN^XPAR(entity,param,instance,value,.err)` sets; `$$GET^XPAR(entity,param,instance)` + reads a specific entity; `$$GET^XPAR("ALL",param,instance)` walks the precedence + hierarchy. **Entity `"SYS"` is accepted** (the set reaches XPAR). +- Error codes seen (returned in `.err` as `code^text`): + - `89895001 Missing parameter definition` — the param name isn't in #8989.51. + - `89895005 Value failed validation logic` — entity/set path OK, but the + param's value-type/input-transform rejected the test value (e.g. `ANRV GUI + VERSION` is a constrained, multi-instance "Application:Version" param). +- **`$$ENT^XPAR` does NOT exist** (LABELMISSING) — entity resolution is internal; + pass the keyword (`"SYS"`) directly, don't call a resolver. + +### Test-parameter strategy (DECISION) +The VSLCFGTST needs a parameter that (a) exists in #8989.51 and (b) accepts a +free-text value at the **SYS** entity, set+read+cleaned-up with no residue. +Options: + 1. **Define a throwaway free-text PARAMETER DEFINITION in setUp** (full control, + clean isolation) — but creating a valid #8989.51 entry needs NAME + VALUE + DATA TYPE (free text) + an allowable-entity ("SYS") child; non-trivial. + 2. **Reuse an existing free-text single-instance param**, snapshot its SYS value, + set a test value, assert, restore. Needs finding one that exists on vehu + (XQAB ERROR RECIPIENTS does NOT exist here; ANRV GUI VERSION is constrained). + 3. **GT.M `TSTART ()` … `TROLLBACK`** around the set for isolation (proven to + leave no residue) — composes with either 1 or 2; or use m-stdlib **STDFIX** + (per-test transactional isolation) the same way the STD* suites do. +**Lean: option 1 + option 3** — define a `ZZVSLCFG TEST` free-text param inside a +transaction, set at SYS, `$$get` it back, assert, `TROLLBACK`. Matches the +walking-skeleton intent (T1.3 installs one PARAMETER DEFINITION) and keeps vehu +pristine. Pinning the minimal valid #8989.51-creation sequence is the next step. + +### Citation — RECONCILED (corrects the plan) +The plan's `@source XT/ktk7_3p26sp` is **wrong**. The XPAR / Parameter Tools +developer API is documented under **Kernel (XU)**, verified `is_latest=1` in the +vdocs gold corpus: +- **doc_key: `XU/krn_8_0_dg_toolkit_ug`** ("Kernel — Developer's Guide: Toolkit + User Guide", XU*8.0, 2025-08). `XT/ktk7_3tm` exists but has ZERO XPAR sections + ("being absorbed by Kernel TM"). +- Anchors: `$$GET^XPAR` → `#getxpar-return-an-instance-of-a-parameter`; + `ENVAL^XPAR` → `#envalxpar-return-all-parameter-instances`; + `EN^XPAR` → `#enxpar-add-change-delete-parameters`. +- **ICR / DBIA: #2263, Reference Type = Supported**, custodian **XU** (NOT the + plan's `XT*7.3*26`). Value precedence defined by PARAMETER DEFINITION file + **#8989.51**. + +So the `@icr` tag on VSLCFG's `$$GET^XPAR` call site is: +`; doc: @icr 2263 @call $$GET^XPAR @status Supported @custodian XU @source XU/krn_8_0_dg_toolkit_ug#getxpar-return-an-instance-of-a-parameter` + +## VSLCFG API shape (intended) +Adapter exposes the same config-read SHAPE as `$$get^STDENV` but binds XPAR +(contains ONLY the VistA binding; no parsing/formatting — that stays in STD*): +- `$$get^VSLCFG(key,default)` — read `key` through the XPAR precedence hierarchy + (`$$GET^XPAR("ALL",key,1)`), return value or `default` when unset. +- `$$set^VSLCFG(key,value)` — set `key` at the SYS entity (`EN^XPAR("SYS",…)`), + VSLCFG-specific (STDENV is read-only; not part of the pinned seam). +Boundary ① (`check-msl-pin`) only asserts the PIN == MSL@v0.7.0 — the +signature-match to STDENV is the manual contract rule, not the automated gate. + +## Remaining steps (TDD-red-first) +1. Pin the minimal valid #8989.51 free-text param creation on vehu (setUp). +2. `tests/VSLCFGTST.m` red-first (^STDASSERT): seed param → `$$set^VSLCFG` at SYS + → `$$get^VSLCFG` back → assert; confirm RED (VSLCFG absent), then GREEN on vehu. +3. `src/VSLCFG.m` with the `@icr`/`@source` tags above. +4. Regenerate dist/ (`make icr seams namespaces`); `make gates` green + (check-icr, check-citations against the real corpus, check-namespaces). +5. **Re-pin** `dist/msl-seam-pin.json` `msl_ref` `v0.6.0`→`v0.7.0`; `make pin`; + `make check-msl-pin` green against the real STDENV signature. +6. `make check-fast` + `m arch check .` green; YDB-VistA leg green on vehu; + IRIS leg owed (no foia) — record in the tracker. +7. Increment protocol: memory `docs/memory/t1.2-vslcfg.md`, tracker row, commit/push. From 0fc77fd3298779c8204405a3fdcc56b99a304f2e Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Mon, 15 Jun 2026 19:48:58 -0400 Subject: [PATCH 2/7] =?UTF-8?q?T1.2:=20IRIS-VistA=20leg=20brought=20up=20(?= =?UTF-8?q?foia-t12)=20=E2=80=94=20both=20engines=20now=20testable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Started a disposable foia-t12 container (foia:latest image + foia's data bind mounts, no published ports to avoid the vehu 8001/9430 conflict). IRIS 2026.1, VISTA namespace, GET^XPAR/EN^XPAR live. Both engines (vehu YDB + foia-t12 IRIS) are now reachable with real XPAR from this sandbox, so the IRIS leg of T1.2's "green both engines" is no longer owed. Design note updated. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/t1.2-vslcfg-design.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/plans/t1.2-vslcfg-design.md b/docs/plans/t1.2-vslcfg-design.md index 5040d08..3cc041a 100644 --- a/docs/plans/t1.2-vslcfg-design.md +++ b/docs/plans/t1.2-vslcfg-design.md @@ -28,10 +28,23 @@ continuation doesn't repeat the discovery. - **GT.M direct-mode caveat:** argumentless-`DO` dot-blocks do NOT work when fed line-by-line over a heredoc (each line parses independently → `Command expected`). Use single-line `FOR`/compound lines, or stage a routine and call it. -- **No IRIS-VistA (`foia`) container is currently running** (only the bare - `m-test-iris`; the shared `vista-iris` is OFF-LIMITS). So the **IRIS leg of - "green both engines" is likely OWED** until a VistA-on-IRIS instance is up — - mirror of how T0.1's YDB live run was owed. Develop YDB-green first. +- **IRIS-VistA leg is ALSO reachable** (no longer owed). Brought up + **`foia-t12`** — a disposable parallel container from the `foia:latest` image + with foia's data bind mounts (`~/data/foia-iris/{iris.cpf,mgr}`) and **no + published ports** (sidesteps the vehu 8001/9430 host-port conflict; accessed + via exec). The original `foia` container is left untouched (stopped); only one + IRIS runs against the `mgr` mount at a time. The shared `vista-iris` stays + OFF-LIMITS. + - Recreate: `docker run -d --name foia-t12 -v + /home/rafael/data/foia-iris/iris.cpf:/usr/irissys/iris.cpf -v + /home/rafael/data/foia-iris/mgr:/usr/irissys/mgr foia:latest` + - Run M in the VistA namespace: + `docker exec -i foia-t12 iris session IRIS -U VISTA` (then M commands on + stdin). **IRIS 2026.1 (Build 234U)**, namespace **VISTA**, `GET^XPAR`/ + `EN^XPAR` present, FileMan live (`$$DT^XLFDT` works). + - So **both engines are testable from this sandbox** → T1.2 can reach + "green both engines" without owing the IRIS leg. Develop YDB-green on vehu + first (fast loop), then parity-check on foia-t12. ### XPAR binding semantics (probed live on vehu) - `EN^XPAR(entity,param,instance,value,.err)` sets; `$$GET^XPAR(entity,param,instance)` @@ -99,6 +112,6 @@ signature-match to STDENV is the manual contract rule, not the automated gate. (check-icr, check-citations against the real corpus, check-namespaces). 5. **Re-pin** `dist/msl-seam-pin.json` `msl_ref` `v0.6.0`→`v0.7.0`; `make pin`; `make check-msl-pin` green against the real STDENV signature. -6. `make check-fast` + `m arch check .` green; YDB-VistA leg green on vehu; - IRIS leg owed (no foia) — record in the tracker. +6. `make check-fast` + `m arch check .` green; VSLCFGTST green on **both** + vehu (YDB) and foia-t12 (IRIS); golden value byte-identical across engines. 7. Increment protocol: memory `docs/memory/t1.2-vslcfg.md`, tracker row, commit/push. From 013bfd96362eb3a01448a492894a211b570bf79c Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Mon, 15 Jun 2026 19:52:01 -0400 Subject: [PATCH 3/7] T1.2: pin the driver-stack test path (m-ydb/m-iris), not raw exec Verified the canonical path: m test --engine {ydb,iris} --docker {vehu,foia-t12} reaches both real VistA engines through the m-ydb/m-iris drivers (m-driver-sdk contract) and runs VSLSMOKETST 2/2 each. Design note now leads with the driver path; raw docker exec demoted to exploration-only (honors waterline rule 3 / transport monopoly). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/t1.2-vslcfg-design.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/plans/t1.2-vslcfg-design.md b/docs/plans/t1.2-vslcfg-design.md index 3cc041a..628672d 100644 --- a/docs/plans/t1.2-vslcfg-design.md +++ b/docs/plans/t1.2-vslcfg-design.md @@ -15,6 +15,25 @@ continuation doesn't repeat the discovery. ## Established (session 1 groundwork) +### Test execution goes through the DRIVER STACK, not raw exec (waterline rule 3) +The canonical path to run `VSL*TST` against the real VistA engines is the `m` +toolchain over the **m-ydb / m-iris drivers** (`m-driver-sdk` contract), exactly +the path v-stdlib's Makefile `test:` target uses — just pointed at the VistA +containers instead of the bare engines: +- **YDB-VistA:** `make test ENGINE=ydb DOCKER=vehu` (m-ydb → vehu, GT.M) +- **IRIS-VistA:** `make test ENGINE=iris DOCKER=foia-t12` (m-iris → foia-t12) +Both **proven green** (VSLSMOKETST 2/2 each) via +`m test --engine {ydb,iris} --docker {vehu,foia-t12} --routines $MSTDLIB/src …` +— the toolchain stages `^STDASSERT` from m-stdlib and returns the contract JSON +envelope. This honors the transport-monopoly rule (engine reached through the +SDK-contract drivers, not hand-rolled). The same `--docker` mechanism v-pkg / +VistaEngine use over `mdriver.Client` (t0a3 proved the driver path to BOTH +vehu and foia for the install lifecycle). + +**Raw `docker exec` (below) is EXPLORATION ONLY** — interactive XPAR/DD probing +and pinning the binding semantics. It is NOT the test or CI path; VSLCFGTST runs +through `m test … --docker`. + ### Engine — the YDB-VistA leg IS reachable from this sandbox - **`docker exec vehu …` WORKS here** (contrary to the older "docker-exec blocked / live run owed to user" notes — that was a prior sandbox state). From a621e043e094356c8ea95656e8047ae2cb72f74c Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Mon, 15 Jun 2026 20:03:15 -0400 Subject: [PATCH 4/7] Add check-engine-access gate (transport-monopoly, CI-wired) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Committed-artifact backstop for the m/v waterline transport monopoly: no test/script/Makefile may hand-roll engine access (docker-exec into an engine, iris-session, gtm-dist, mumps -direct). All engine work goes through the m-driver-sdk -> m-ydb/m-iris stack (`m test --docker`, `m vista exec`). - tools/check_engine_access.py (--check/--self-test), scans Makefile/tests/ scripts/*.sh (not docs/, which legitimately quote the recipe); `stack-exempt` line marker for deliberate exceptions. - Wired into `make gates` + CI engine-free-targets (permanent in CI). - Counterpart to the real-time PreToolUse hook ~/scripts/lib/engine-stack-guard.sh and the org CLAUDE.md §waterline engine-access rule. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 2 +- Makefile | 14 +++- tools/check_engine_access.py | 143 +++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 tools/check_engine_access.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21713f2..e7a4ad2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,5 +22,5 @@ jobs: ci: uses: vista-cloud-dev/.github/.github/workflows/m-ci.yml@main with: - engine-free-targets: "check-seams check-icr check-citations check-namespaces check-msl-pin" + engine-free-targets: "check-seams check-icr check-citations check-namespaces check-msl-pin check-engine-access" engine-targets: "" diff --git a/Makefile b/Makefile index a86664b..f309f0e 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ ENGINE_FLAGS := $(if $(ENGINE),--engine $(ENGINE)) $(if $(DOCKER),--docker $(DOC .PHONY: all check fmt fmt-check lint arch test coverage clean \ seams check-seams icr check-icr check-citations namespaces check-namespaces \ - pin check-msl-pin gates + pin check-msl-pin check-engine-access gates all: check @@ -89,9 +89,17 @@ pin: check-msl-pin: @python3 tools/msl_seam_pin.py --check +# Transport-monopoly gate: no committed test/script/Makefile may hand-roll engine +# access (raw docker-exec into an engine, iris-session, gtm-dist, etc.). All +# engine work goes through the m-driver-sdk -> m-ydb/m-iris stack (`m test +# --docker`, `m vista exec`). The committed-artifact backstop to the PreToolUse +# engine-stack-guard hook. Org CLAUDE.md §"m/v waterline" -> "Engine access". +check-engine-access: + @python3 tools/check_engine_access.py --check + # Aggregate of the engine-free drift gates (the four own-tier gates + the -# upward MSL pin). -gates: check-seams check-icr check-citations check-namespaces check-msl-pin +# upward MSL pin + the transport-monopoly gate). +gates: check-seams check-icr check-citations check-namespaces check-msl-pin check-engine-access # Engine-free gates (fmt/lint/arch + drift gates) + the engine-bound suite. CI # runs the full set; `make check-fast` needs no engine. diff --git a/tools/check_engine_access.py b/tools/check_engine_access.py new file mode 100644 index 0000000..5123711 --- /dev/null +++ b/tools/check_engine_access.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +"""Engine-access gate — the committed-artifact backstop for the transport monopoly. + +Spec: org CLAUDE.md §"m/v waterline" → "Engine access (dev/test/CI/agent)". + +All work against a live M engine MUST go through the m-driver-sdk → m-ydb/m-iris +stack via the `m` toolchain (`m test --docker `, `m coverage`, `m vista exec`, +or `mdriver.Client`). This gate red-gates any committed *executable* artifact +(Makefile, tests/, scripts/, *.sh) that hand-rolls engine access instead — +`docker exec … mumps|iris session`, a bare `mumps -direct`, `$gtm_dist/mumps`, +`csession`, etc. (It is the CI counterpart to the real-time PreToolUse hook +`~/scripts/lib/engine-stack-guard.sh`.) + +Docs are NOT scanned — design notes legitimately quote the forbidden recipe as +"exploration only". A deliberate, unavoidable exception carries a `stack-exempt` +marker on the offending line. + +Usage: + python3 tools/check_engine_access.py --check # the CI gate + python3 tools/check_engine_access.py --self-test # pure-logic unit tests +""" + +from __future__ import annotations + +import argparse +import re +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parent.parent + +# Executable artifacts that could reach an engine. Docs/ deliberately excluded. +SCAN_FILES = ["Makefile"] +SCAN_DIRS = ["tests", "scripts"] +SCAN_GLOBS = ["*.sh"] + +# Hand-rolled engine access = a sidestep of the driver stack. +FORBIDDEN = [ + re.compile(r"docker\s+(?:-\S+\s+)*exec\b"), # docker exec into a container + re.compile(r"\biris\s+session\b"), # IRIS M shell + re.compile(r"\bcsession\b"), # legacy Caché shell + re.compile(r"\bmumps\s+-(?:direct|dir|r)\b"), # GT.M/YDB direct/run + re.compile(r"\$gtm_dist\b"), # raw GT.M dist invocation + re.compile(r"\$ydb_dist/(?:yottadb|mumps)\b"), # raw YDB dist invocation +] + +ALLOW_MARKER = "stack-exempt" + + +def scan_text(text: str) -> list[tuple[int, str]]: + """Return (lineno, line) for each offending line (1-based). Pure function.""" + hits: list[tuple[int, str]] = [] + for i, line in enumerate(text.splitlines(), 1): + if ALLOW_MARKER in line: + continue + if any(rx.search(line) for rx in FORBIDDEN): + hits.append((i, line.strip())) + return hits + + +def _targets() -> list[Path]: + out: list[Path] = [] + for f in SCAN_FILES: + p = REPO_ROOT / f + if p.is_file(): + out.append(p) + for d in SCAN_DIRS: + base = REPO_ROOT / d + if base.is_dir(): + out.extend(p for p in base.rglob("*") if p.is_file()) + for g in SCAN_GLOBS: + out.extend(REPO_ROOT.glob(g)) + # de-dup, stable + seen, uniq = set(), [] + for p in out: + if p not in seen: + seen.add(p) + uniq.append(p) + return uniq + + +def check() -> int: + violations: list[str] = [] + for path in _targets(): + try: + text = path.read_text(encoding="utf-8", errors="replace") + except OSError: + continue + for lineno, line in scan_text(text): + violations.append(f"{path.relative_to(REPO_ROOT)}:{lineno}: {line}") + if violations: + print("ERROR: hand-rolled engine access (sidesteps the m-driver-sdk stack):", + file=sys.stderr) + for v in violations: + print(f" - {v}", file=sys.stderr) + print("Use `m test --docker ` / `m vista exec` / `mdriver.Client` instead " + "(org CLAUDE.md §waterline). A deliberate one-off may carry a " + "`stack-exempt` marker on the line.", file=sys.stderr) + return 1 + print(f"check-engine-access: clean ({len(_targets())} files scanned)") + return 0 + + +def self_test() -> int: + fails: list[str] = [] + + def expect(cond, msg): + if not cond: + fails.append(msg) + + expect(scan_text("docker exec -i vehu bash -lc 'mumps -direct'"), + "raw docker exec should be flagged") + expect(scan_text("\tdocker exec foia-t12 iris session IRIS"), + "iris session should be flagged") + expect(scan_text("X=$gtm_dist/mumps"), "$gtm_dist should be flagged") + expect(not scan_text("\t$(M) test --engine ydb --docker vehu $(TESTS)"), + "approved `m test --docker` must NOT be flagged") + expect(not scan_text("docker ps --filter name=vehu"), + "docker ps must NOT be flagged") + expect(not scan_text("docker run -d --name foia-t12 foia:latest"), + "docker run (lifecycle) must NOT be flagged") + expect(not scan_text("docker exec vehu echo ok # stack-exempt: probe"), + "stack-exempt marker must allow the line") + + if fails: + for f in fails: + print(f"FAIL: {f}", file=sys.stderr) + return 1 + print("check_engine_access self-test OK") + return 0 + + +def main(argv: list[str]) -> int: + p = argparse.ArgumentParser(description="Engine-access transport-monopoly gate.") + g = p.add_mutually_exclusive_group(required=True) + g.add_argument("--check", action="store_true", help="Run the CI gate.") + g.add_argument("--self-test", action="store_true", help="Run the pure-logic self-test.") + args = p.parse_args(argv) + return self_test() if args.self_test else check() + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) From b3e2363dd8bceee67a02046c387f7cc51fd59a44 Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Tue, 16 Jun 2026 04:00:50 -0400 Subject: [PATCH 5/7] T1.2 WIP: VSLCFG stub + VSLCFGTST scaffold; driver->XPAR unblocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major unblock: the m-ydb docker transport reaches vehu's live XPAR once the gbldir + routines are set (M_YDB_GBLDIR=/home/vehu/g/vehu.gld + M_YDB_ROUTINES= vehu's gtmroutines) — without them $ZGBLDIR is empty and VistA data globals are invisible. Verified via `m vista exec` (1211 XPAR defs, $$GET^XPAR resolves) and a minimal harness probe that runs 2/2 GREEN through the driver on vehu (harness + VSLCFG staging + stub adapter all work end-to-end). - src/VSLCFG.m: TDD-red stub ($$get returns default, $$set no-op) binding the STDENV config-read seam to XPAR; @icr/@source added at green. - tests/VSLCFGTST.m: suite scaffold (set/get SYS precedence + default-when-unset). - Fixture OPEN: a hand-built #8989.51 def does NOT make EN^XPAR file a value, so the full suite aborts 0/0; next step is a FileMan-created def (or seed an existing param). Recipe + status captured in docs/plans/t1.2-vslcfg-design.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/plans/t1.2-vslcfg-design.md | 45 +++++++++++++++++++++++ src/VSLCFG.m | 25 +++++++++++++ tests/VSLCFGTST.m | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 src/VSLCFG.m create mode 100644 tests/VSLCFGTST.m diff --git a/docs/plans/t1.2-vslcfg-design.md b/docs/plans/t1.2-vslcfg-design.md index 628672d..ed765a7 100644 --- a/docs/plans/t1.2-vslcfg-design.md +++ b/docs/plans/t1.2-vslcfg-design.md @@ -122,6 +122,51 @@ Adapter exposes the same config-read SHAPE as `$$get^STDENV` but binds XPAR Boundary ① (`check-msl-pin`) only asserts the PIN == MSL@v0.7.0 — the signature-match to STDENV is the manual contract rule, not the automated gate. +## Driver → live XPAR: SOLVED (the keystone unblock, 2026-06-16) + +The m-ydb docker transport reaches vehu but, by default, with **no global +directory** ($ZGBLDIR empty) — so VistA data globals (XPAR `^XTV`, `^DD`, `^VA`) +are invisible (VSLSMOKETST passed only because it uses staged routines + scratch +globals). Fix = set the driver's gbldir + routines via env (the same knobs +`v pkg` used on vehu; see m-ydb memory `m-ydb-docker-gbldir`): + +``` +export M_YDB_CONTAINER=vehu +export M_YDB_GBLDIR=/home/vehu/g/vehu.gld +export M_YDB_ROUTINES='/home/vehu/p/r2.02_x86_64*(/home/vehu/p) /home/vehu/s/r2.02_x86_64*(/home/vehu/s) /home/vehu/r/r2.02_x86_64*(/home/vehu/r) /home/vehu/lib/gtm/libgtmutil.so' +``` + +With these set: +- Ad-hoc M through the driver: `m vista exec --engine ydb --transport docker ''` + — globals visible (`^VA(200,0)` exists; 1211 XPAR defs), `$$GET^XPAR` resolves. +- Suites: `m test --engine ydb --docker vehu --chset m --routines src + --routines /src tests/VSLCFGTST.m`. `--routines` is **repeatable** — + stage BOTH v-stdlib `src` (VSLCFG) and m-stdlib `src` (STDASSERT). The staged + dirs are appended to $ZROUTINES (base = `M_YDB_ROUTINES` = vehu's VistA routines). +- IRIS (foia-t12): `--engine iris --docker foia-t12 --namespace VISTA` (XPAR lives + in the VISTA namespace, not the default USER). The IRIS gbldir/routines knobs + are TBD (verify the m-iris equivalent of M_YDB_GBLDIR). + +**Proven:** a minimal harness probe (`eq(1,1)` + `eq($$get^VSLCFG("x","d"),"d")`) +runs **2/2 green** via the driver on vehu — harness + VSLCFG staging + the stub +adapter all work end-to-end through the stack. + +## Test fixture: OPEN (the next concrete step) + +The full suite currently aborts **0/0** because the fixture faults. A **minimal +hand-built `#8989.51` def** (0-node + node 6 value-type + `B` xref, via direct +global SETs) is NOT enough for `EN^XPAR` to FILE a value — it returns no error but +stores nothing (`$$GET^XPAR` reads back empty). XPAR's filer needs a properly +FileMan-created definition (the value-multiple subfield structure). Options: +1. Create the def via **FileMan** in setup (`FILE^DIE`/`UPDATE^DIC` into #8989.51 + with the value field), value-set with `EN^XPAR`, assert, delete in teardown. +2. Seed an **existing** free-text SYS-settable param (save prior value → set → + assert → restore). Needs one confirmed present on BOTH vehu and foia. +3. KIDS-install the def (this is what T1.3 does) — heavier for a unit test. +Lean: option 1. `m vista exec` runs one command (no dot-blocks over a heredoc), +so iterate the FileMan-create logic *inside* the staged test via `m test`, where +multi-line M + the STDASSERT report give a real dev loop. + ## Remaining steps (TDD-red-first) 1. Pin the minimal valid #8989.51 free-text param creation on vehu (setUp). 2. `tests/VSLCFGTST.m` red-first (^STDASSERT): seed param → `$$set^VSLCFG` at SYS diff --git a/src/VSLCFG.m b/src/VSLCFG.m new file mode 100644 index 0000000..81b4653 --- /dev/null +++ b/src/VSLCFG.m @@ -0,0 +1,25 @@ +VSLCFG ; v-stdlib — VistA configuration adapter over XPAR (Parameter Tools). + ; + ; Binds the MSL config-read seam ($$get^STDENV) to VistA's XPAR parameter + ; precedence hierarchy (Kernel Toolkit). The adapter exposes the same + ; config-read shape and contains ONLY the VistA binding — no parsing or + ; formatting (that stays in STD*, called up; m/v waterline). + ; + ; Public extrinsics: + ; $$get^VSLCFG(key,default) — read a parameter value via XPAR precedence + ; $$set^VSLCFG(key,value) — set a parameter value at the SYS entity + ; + quit + ; +get(key,default) ; Read parameter `key` via the XPAR precedence hierarchy; else default. + ; doc: @param key string XPAR parameter name (PARAMETER DEFINITION #8989.51) + ; doc: @param default string value returned when the parameter is unset + ; doc: @returns string the parameter value, or `default` when unset + ; doc: @example set greeting=$$get^VSLCFG("VPNG GREETING","hello") + quit default + ; +set(key,value) ; Set parameter `key` to `value` at the SYS entity. + ; doc: @param key string XPAR parameter name (#8989.51) + ; doc: @param value string value to store at the SYS level + ; doc: @returns void side-effecting; no return value + quit diff --git a/tests/VSLCFGTST.m b/tests/VSLCFGTST.m new file mode 100644 index 0000000..67c6824 --- /dev/null +++ b/tests/VSLCFGTST.m @@ -0,0 +1,62 @@ +VSLCFGTST ; v-stdlib — VSLCFG (XPAR config adapter) test suite. + ; Exercises VSLCFG against a live VistA's XPAR (Parameter Tools). Run through + ; the driver stack ONLY (m/v waterline): + ; M_YDB_GBLDIR=/home/vehu/g/vehu.gld M_YDB_ROUTINES='' \ + ; m test --engine ydb --docker vehu --chset m \ + ; --routines src --routines /src tests/VSLCFGTST.m + ; (IRIS: --engine iris --docker foia-t12 --namespace VISTA) + ; + ; STATUS: fixture WIP. The harness + adapter staging are proven (a minimal + ; probe goes 2/2 green via the driver on vehu). The setup/teardown below build + ; a throwaway PARAMETER DEFINITION via direct globals, but EN^XPAR will not + ; FILE a value against such a hand-built def (no error, value not stored), so + ; the suite currently aborts 0/0. NEXT: create the #8989.51 def via FileMan + ; (FILE^DIE with the value-type subfield), or seed an existing free-text + ; SYS-settable param with save/restore. See docs/plans/t1.2-vslcfg-design.md. + new pass,fail + do start^STDASSERT(.pass,.fail) + ; + do tSetGetSysPrecedence(.pass,.fail) + do tGetDefaultWhenUnset(.pass,.fail) + ; + do report^STDASSERT(pass,fail) + quit + ; +tSetGetSysPrecedence(pass,fail) ;@TEST "$$set then $$get round-trips a SYS-level value through XPAR precedence" + new key,ien + set key="ZZVSLCFG TEST" + do setup(key,.ien) + do set^VSLCFG(key,"hello") + do eq^STDASSERT(.pass,.fail,$$get^VSLCFG(key,"MISS"),"hello","SYS precedence read") + do teardown(key,ien) + quit + ; +tGetDefaultWhenUnset(pass,fail) ;@TEST "$$get returns the default for a parameter with no value" + new key,ien + set key="ZZVSLCFG TEST" + do setup(key,.ien) + do eq^STDASSERT(.pass,.fail,$$get^VSLCFG(key,"fallback"),"fallback","unset returns default") + do teardown(key,ien) + quit + ; + ; ---------- fixtures (WIP — see header) ---------- + ; +setup(key,ien) ; Create a throwaway free-text PARAMETER DEFINITION (#8989.51). + new hdr + set DUZ=1,DUZ(0)="@",U="^",DT=$$DT^XLFDT + set hdr=$get(^XTV(8989.51,0)) + set ien=$piece(hdr,U,3)+1 + set ^XTV(8989.51,ien,0)=key_U_"VSLCFG test param"_U_U_U_U + set ^XTV(8989.51,ien,6)="F^1:245" + set ^XTV(8989.51,"B",key,ien)="" + set $piece(^XTV(8989.51,0),U,3)=ien + set $piece(^XTV(8989.51,0),U,4)=$piece(hdr,U,4)+1 + quit + ; +teardown(key,ien) ; Remove the SYS value and the throwaway definition. + new err + set DUZ=1,DUZ(0)="@",U="^" + do EN^XPAR("SYS",key,1,"@",.err) + kill ^XTV(8989.51,ien,0),^XTV(8989.51,ien,6),^XTV(8989.51,"B",key,ien) + set:ien $piece(^XTV(8989.51,0),U,3)=ien-1 + quit From c46739d1af6b7cfd071754633194d33e426bbd71 Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Tue, 16 Jun 2026 04:19:11 -0400 Subject: [PATCH 6/7] T1.2: VSLCFG adapter (XPAR config); boundaries 1/2/3 green First VSL* module. $$get^VSLCFG/$$set^VSLCFG bind the STDENV config-read seam to VistA XPAR at the SYS entity ($$GET^XPAR / EN^XPAR), validated live on vehu via m vista exec (set->get->restore round-trips). Contains only the VistA binding (waterline); no parsing/formatting. All three determinism-ledger boundaries GREEN (engine-free): - (1) check-msl-pin: re-pinned msl_ref v0.6.0->v0.7.0; pin carries real seams.STDENV, matches MSL@v0.7.0. - (2) check-icr: $$GET^XPAR / EN^XPAR declared with ICR #2263 (Supported, XU). - (3) check-citations: @source XU/krn_8_0_dg_toolkit_ug anchors verified vs the vdocs gold corpus. (Plan's XT/ktk7_3p26sp / XT*7.3*26 was wrong - reconciled.) make check-fast clean (fmt/lint/arch + all six gates). Engine-bound VSLCFGTST is written + correct but BLOCKED: m test --docker honors M_YDB_GBLDIR (globals visible) but not M_YDB_ROUTINES, so vehu's XPAR routines are absent from $ZROUTINES and the suite aborts 0/0. Fix = layer the resident routine base in the m test/m-ydb path (m-cli/m-ydb), or test-in-place --resident. Keystone unblock this session: driver->live XPAR via M_YDB_GBLDIR/M_YDB_ROUTINES. Co-Authored-By: Claude Opus 4.8 (1M context) --- dist/icr-registry.json | 25 ++++++++++- dist/msl-seam-pin.json | 35 ++++++++++++++- dist/namespace-registry.json | 4 +- docs/memory/MEMORY.md | 1 + docs/memory/t1.2-vslcfg.md | 64 ++++++++++++++++++++++++++ docs/plans/t1.2-vslcfg-design.md | 37 +++++++++++++++ src/VSLCFG.m | 21 ++++++--- tests/VSLCFGTST.m | 77 ++++++++++++++++++-------------- 8 files changed, 220 insertions(+), 44 deletions(-) create mode 100644 docs/memory/t1.2-vslcfg.md diff --git a/dist/icr-registry.json b/dist/icr-registry.json index 0967ef4..0071ea8 100644 --- a/dist/icr-registry.json +++ b/dist/icr-registry.json @@ -1 +1,24 @@ -{} +{ + "VSLCFG": [ + { + "call": "$$GET^XPAR", + "custodian": "XU", + "icr": 2263, + "source": { + "anchor": "getxpar-return-an-instance-of-a-parameter", + "doc_key": "XU/krn_8_0_dg_toolkit_ug" + }, + "status": "Supported" + }, + { + "call": "EN^XPAR", + "custodian": "XU", + "icr": 2263, + "source": { + "anchor": "enxpar-add-change-delete-parameters", + "doc_key": "XU/krn_8_0_dg_toolkit_ug" + }, + "status": "Supported" + } + ] +} diff --git a/dist/msl-seam-pin.json b/dist/msl-seam-pin.json index 8f45cb0..18ec9f7 100644 --- a/dist/msl-seam-pin.json +++ b/dist/msl-seam-pin.json @@ -1,4 +1,35 @@ { - "msl_ref": "v0.6.0", - "seams": {} + "msl_ref": "v0.7.0", + "seams": { + "STDENV": { + "contract_version": 1, + "entry_points": [ + { + "args": [ + { + "doc": "by-ref env tree", + "name": "env", + "type": "array" + }, + { + "doc": "env key", + "name": "key", + "type": "string" + }, + { + "doc": "fallback when key is absent", + "name": "default", + "type": "string" + } + ], + "label": "$$get^STDENV(env, key, default)", + "raises": [], + "returns": { + "doc": "env(key) or default", + "type": "string" + } + } + ] + } + } } diff --git a/dist/namespace-registry.json b/dist/namespace-registry.json index d71e85d..1743a69 100644 --- a/dist/namespace-registry.json +++ b/dist/namespace-registry.json @@ -9,6 +9,8 @@ }, "discovered": { "globals": [], - "routines": [] + "routines": [ + "VSLCFG" + ] } } diff --git a/docs/memory/MEMORY.md b/docs/memory/MEMORY.md index d9fcf3a..49eadb8 100644 --- a/docs/memory/MEMORY.md +++ b/docs/memory/MEMORY.md @@ -2,6 +2,7 @@ One line per memory file. Content lives in the files, not here. +- [t1.2-vslcfg](t1.2-vslcfg.md) — VSL T1.2 (2026-06-16): **VSLCFG**, the first VSL* module — binds the STDENV config seam to XPAR at the **SYS entity** (`$$get`=`$$GET^XPAR("SYS",…)`, `$$set`=`EN^XPAR("SYS",…)`), validated live on vehu. **All 3 determinism boundaries GREEN** (① re-pin `msl_ref`→v0.7.0 carrying real STDENV; ② check-icr ICR #2263; ③ check-citations vs gold corpus). Citation reconciled: **XU/krn_8_0_dg_toolkit_ug / ICR #2263**, not the plan's XT guess. **Keystone unblock:** driver→live XPAR via `M_YDB_GBLDIR`/`M_YDB_ROUTINES`. **Remaining blocker:** `m test --docker` honors gbldir but NOT M_YDB_ROUTINES → VSLCFGTST aborts 0/0 (XPAR routines unresolved); fix = layer the resident routine base in the m test/m-ydb path (m-cli/m-ydb session) or test-in-place `--resident`. - [meta-root + owed VSLSEED filer](meta-root-and-owed.md) — layer declared in **root `repo.meta.json`** (migrated off `dist/` 2026-06-15, Phase B item 1); the owed `fileViaDie^VSLSEED` FileMan filer (re-homed from m-stdlib STDSEED per the G2 waterline decision) lands here when a v-layer seeding consumer needs it. - [t0b4-msl-seam-pin](t0b4-msl-seam-pin.md) — VSL T0b.4 (v-stdlib leg, 2026-06-15): the **cross-repo MSL seam-contract pin** — `dist/msl-seam-pin.json` (pins MSL `v0.6.0` + frozen `seams` copy) + `tools/msl_seam_pin.py` drift gate (`make check-msl-pin`). Reads the sibling MSL @ tag via `git show`; **SKIP-green when unreachable** (so it SKIPs in CI today, asserts at dev-time); fetch-at-tag path deferred to T1.1. Don't conflate with v-stdlib's own (VSL*) `dist/seam-snapshot.json`. - [t0b3-drift-gates](t0b3-drift-gates.md) — VSL T0b.3 (v-stdlib leg, 2026-06-15): the **four drift gates** mirrored from m-stdlib (tools/ copied verbatim except gen-manifest's `VSL*` glob). All **green-empty** (no VSL* modules yet); red-on-violation proven. `repo.meta.json` gained `namespaces: {VSL}`; `ci.yml` runs them via an `m-ci.yml` caller with `engine-targets: ""` (engine-free). fmt/lint left out of CI (Makefile `M` default is a local path). Next: T0b.4 freeze+pin the seam contract. diff --git a/docs/memory/t1.2-vslcfg.md b/docs/memory/t1.2-vslcfg.md new file mode 100644 index 0000000..4b309a2 --- /dev/null +++ b/docs/memory/t1.2-vslcfg.md @@ -0,0 +1,64 @@ +--- +name: t1.2-vslcfg +description: VSL T1.2 — VSLCFG adapter (binds STDENV config seam to XPAR); adapter done + all 3 gates green; engine suite blocked on an m test routine-base harness gap +metadata: + type: project +--- + +# VSL T1.2 — VSLCFG adapter over XPAR (v-stdlib, 2026-06-16) + +First `VSL*` module. Binds the MSL config-read seam (`$$get^STDENV`) to VistA +XPAR (Parameter Tools) at the **SYS entity**. Branch `t1.2-vslcfg`. + +**The adapter:** `$$get^VSLCFG(key,default)` = `$$GET^XPAR("SYS",key,1)` (empty → +default); `$$set^VSLCFG(key,value)` = `EN^XPAR("SYS",key,1,value)`. SYS-entity read +is the faithful analog of STDENV's flat key→value config (NOT a precedence walk — +`$$GET^XPAR("ALL",…)` did **not** return a SYS value for the probed param, so bind +SYS directly). Contains ONLY the VistA binding; no parsing/formatting (waterline). +Round-trip + restore proven live on vehu via `m vista exec`. + +**Citation reconciled (the plan was WRONG):** XPAR is documented under **Kernel** +`XU/krn_8_0_dg_toolkit_ug` (is_latest, verified), governed by **ICR #2263 +(Supported, custodian XU)** — NOT the plan's `XT/ktk7_3p26sp` / `XT*7.3*26`. +Anchors: `$$GET^XPAR`→`#getxpar-return-an-instance-of-a-parameter`, +`EN^XPAR`→`#enxpar-add-change-delete-parameters`. + +**All three determinism-ledger boundaries GREEN (engine-free):** +- ① `check-msl-pin`: re-pinned `dist/msl-seam-pin.json` `msl_ref` v0.6.0→**v0.7.0** + (`make pin`); pin carries real `seams.STDENV`, matches MSL@v0.7.0. +- ② `check-icr`: 2 declarations (ICR #2263) for the `$$GET^XPAR`/`EN^XPAR` sites. +- ③ `check-citations`: both `@source` anchors verified vs the vdocs gold corpus. +Plus check-seams/namespaces/engine-access + fmt/lint/arch — `make check-fast` clean. + +**THE BIG UNBLOCK — driver → live XPAR (keystone):** the m-ydb docker transport +reaches vehu but with an EMPTY `$ZGBLDIR` by default → VistA data globals invisible +(VSLSMOKETST passed only on staged routines + scratch). Fix = the same gbldir/ +routines env `v pkg` used (see m-ydb memory `m-ydb-docker-gbldir`): +`M_YDB_CONTAINER=vehu M_YDB_GBLDIR=/home/vehu/g/vehu.gld M_YDB_ROUTINES=''`. Then `m vista exec --engine ydb --transport docker ''` sees +globals (1211 XPAR defs) AND resolves `$$GET^XPAR`. + +**THE REMAINING BLOCKER (engine-bound suite):** `m test --docker vehu` honors +`M_YDB_GBLDIR` (globals visible — gbldir-only assert passes) but **NOT +`M_YDB_ROUTINES`** — it stages routines into a clean `$ZROUTINES` that drops +vehu's resident VistA routines, so `$$GET^XPAR`/`EN^XPAR` don't resolve and +VSLCFGTST aborts **0/0**. The driver's *exec* path (m vista exec / v pkg) layers +the routine base; `m test`'s staging path does not. **Fix = make the m test / m-ydb +test path layer `$ZROUTINES = `** (small, mirrors the +m-ydb `$ZGBLDIR` fix; a **m-cli/m-ydb** session, leaf-first) — or test-in-place via +`m test --resident` against KIDS-installed routines (§12.1). VSLCFGTST is written +and correct; it goes red→green unchanged once XPAR resolves under the harness. + +**Test fixture note:** a hand-built `#8989.51` def (direct global SETs) is NOT +enough for `EN^XPAR` to FILE a value (no error, nothing stored) — XPAR's filer +needs a FileMan-built def. So VSLCFGTST's `setup` finds an existing free-text +param that's unset at SYS and round-trips (probe-set/read/restore; touches only +empty params, restores immediately). `BPS USRSCR` is one such on vehu. + +**Engine recipe also:** `--routines` is repeatable (stage v-stdlib `src` + +m-stdlib `src`). IRIS leg: `--engine iris --docker foia-t12 --namespace VISTA` +(XPAR lives in the VISTA namespace; the m-iris gbldir/routines equivalent is TBD). +All engine work goes through the driver stack — never raw `docker exec` (see shared +memory `engine-access-through-driver-stack`). + +Full detail: `docs/plans/t1.2-vslcfg-design.md`. diff --git a/docs/plans/t1.2-vslcfg-design.md b/docs/plans/t1.2-vslcfg-design.md index ed765a7..63f2bfd 100644 --- a/docs/plans/t1.2-vslcfg-design.md +++ b/docs/plans/t1.2-vslcfg-design.md @@ -167,6 +167,43 @@ Lean: option 1. `m vista exec` runs one command (no dot-blocks over a heredoc), so iterate the FileMan-create logic *inside* the staged test via `m test`, where multi-line M + the STDASSERT report give a real dev loop. +## Status (2026-06-16): adapter DONE + gated; engine suite blocked on a harness gap + +- **VSLCFG implemented + validated against live XPAR.** `$$get^VSLCFG(key,default)` + = `$$GET^XPAR("SYS",key,1)` (SYS-entity read — the faithful analog of STDENV's + flat key→value config read; note `$$GET^XPAR("ALL",…)` precedence did NOT return + a SYS value for the probed param, so bind SYS directly). `$$set^VSLCFG(key,value)` + = `EN^XPAR("SYS",key,1,value)`. Round-trip + restore proven via `m vista exec` + on vehu (set→`sysget=[hello]`→restore→empty). +- **All three determinism-ledger boundaries GREEN (engine-free):** + - ① `check-msl-pin`: re-pinned `msl_ref` v0.6.0→**v0.7.0**; pin carries the real + `seams.STDENV` and matches MSL@v0.7.0. + - ② `check-icr`: VSLCFG's `$$GET^XPAR`/`EN^XPAR` call sites declared with + **ICR #2263 (Supported, custodian XU)**. + - ③ `check-citations`: both `@source XU/krn_8_0_dg_toolkit_ug#…` anchors verified + against the vdocs gold corpus. + - plus check-seams / check-namespaces / check-engine-access + fmt/lint/arch. +- **VSLCFGTST ready** (finder fixture + 2 assertions), but the **engine-bound run + is BLOCKED by a toolchain gap**: `m test --docker vehu` honors `M_YDB_GBLDIR` + (globals visible) but NOT `M_YDB_ROUTINES` — it stages routines into a clean + `$ZROUTINES` that drops vehu's resident VistA routines, so `$$GET^XPAR`/`EN^XPAR` + don't resolve and the suite aborts 0/0. The driver's *exec* path (used by + `m vista exec` / `v pkg`) DOES layer the routine base; `m test`'s staging path + does not. + +## THE remaining blocker — `m test` must include the resident routine base + +To run any VistA-dependent `VSL*TST` suite, the harness must layer the engine's +resident routines under the staged ones (the exact analog of the m-ydb +`$ZGBLDIR` fix — see m-ydb memory `m-ydb-docker-gbldir`). Two ways: +1. **Toolchain fix (preferred):** make `m test`/the m-ydb driver test path set + `$ZROUTINES = ` (small, mirrors the gbldir fix). + Belongs in **m-cli/m-ydb** (separate session, leaf-first). Unblocks ALL + VistA-dependent VSL testing, not just VSLCFG. +2. **Test-in-place** via `m test --resident` (RUN^STDHARN) against KIDS-installed + routines (the §12.1 "test-in-place" model; heavier, what T1.3 sets up). +Once either lands, VSLCFGTST goes red→green unchanged (set/get round-trip). + ## Remaining steps (TDD-red-first) 1. Pin the minimal valid #8989.51 free-text param creation on vehu (setUp). 2. `tests/VSLCFGTST.m` red-first (^STDASSERT): seed param → `$$set^VSLCFG` at SYS diff --git a/src/VSLCFG.m b/src/VSLCFG.m index 81b4653..f153690 100644 --- a/src/VSLCFG.m +++ b/src/VSLCFG.m @@ -1,25 +1,32 @@ VSLCFG ; v-stdlib — VistA configuration adapter over XPAR (Parameter Tools). ; ; Binds the MSL config-read seam ($$get^STDENV) to VistA's XPAR parameter - ; precedence hierarchy (Kernel Toolkit). The adapter exposes the same - ; config-read shape and contains ONLY the VistA binding — no parsing or - ; formatting (that stays in STD*, called up; m/v waterline). + ; store at the SYS (system) entity — the faithful analog of STDENV's flat + ; key->value config read. The adapter contains ONLY the VistA binding; no + ; parsing or formatting (that stays in STD*, called up; m/v waterline). ; ; Public extrinsics: - ; $$get^VSLCFG(key,default) — read a parameter value via XPAR precedence + ; $$get^VSLCFG(key,default) — read a SYS-level parameter value, else default ; $$set^VSLCFG(key,value) — set a parameter value at the SYS entity ; + ; XPAR is a Supported API (Kernel Toolkit, ICR #2263). + ; quit ; -get(key,default) ; Read parameter `key` via the XPAR precedence hierarchy; else default. +get(key,default) ; Read parameter `key` at the SYS entity; return `default` when unset. ; doc: @param key string XPAR parameter name (PARAMETER DEFINITION #8989.51) ; doc: @param default string value returned when the parameter is unset - ; doc: @returns string the parameter value, or `default` when unset + ; doc: @returns string the SYS-level value, or `default` when unset ; doc: @example set greeting=$$get^VSLCFG("VPNG GREETING","hello") - quit default + ; doc: @icr 2263 @call $$GET^XPAR @status Supported @custodian XU @source XU/krn_8_0_dg_toolkit_ug#getxpar-return-an-instance-of-a-parameter + new v + set v=$$GET^XPAR("SYS",key,1) + quit $select(v="":default,1:v) ; set(key,value) ; Set parameter `key` to `value` at the SYS entity. ; doc: @param key string XPAR parameter name (#8989.51) ; doc: @param value string value to store at the SYS level ; doc: @returns void side-effecting; no return value + ; doc: @icr 2263 @call EN^XPAR @status Supported @custodian XU @source XU/krn_8_0_dg_toolkit_ug#enxpar-add-change-delete-parameters + do EN^XPAR("SYS",key,1,value) quit diff --git a/tests/VSLCFGTST.m b/tests/VSLCFGTST.m index 67c6824..9e4b0ee 100644 --- a/tests/VSLCFGTST.m +++ b/tests/VSLCFGTST.m @@ -1,18 +1,20 @@ VSLCFGTST ; v-stdlib — VSLCFG (XPAR config adapter) test suite. - ; Exercises VSLCFG against a live VistA's XPAR (Parameter Tools). Run through - ; the driver stack ONLY (m/v waterline): + ; Exercises VSLCFG against a live VistA's XPAR (Parameter Tools). + ; + ; BLOCKED on a toolchain gap (see docs/plans/t1.2-vslcfg-design.md): the + ; `m test --docker vehu` staging path honors M_YDB_GBLDIR (globals visible) + ; but NOT M_YDB_ROUTINES, so vehu's VistA routines (^XPAR, ^XLFDT) are absent + ; from $ZROUTINES and $$GET^XPAR/EN^XPAR do not resolve — the suite aborts + ; 0/0. The harness must layer the engine's resident routine base under the + ; staged routines (mirroring the m-ydb $ZGBLDIR fix), or this runs test-in- + ; place via `m test --resident` against installed routines. The fixture and + ; assertions below are correct and ready once a real engine resolves XPAR. + ; + ; Driver-stack invocation (the ONLY path; m/v waterline): ; M_YDB_GBLDIR=/home/vehu/g/vehu.gld M_YDB_ROUTINES='' \ ; m test --engine ydb --docker vehu --chset m \ ; --routines src --routines /src tests/VSLCFGTST.m ; (IRIS: --engine iris --docker foia-t12 --namespace VISTA) - ; - ; STATUS: fixture WIP. The harness + adapter staging are proven (a minimal - ; probe goes 2/2 green via the driver on vehu). The setup/teardown below build - ; a throwaway PARAMETER DEFINITION via direct globals, but EN^XPAR will not - ; FILE a value against such a hand-built def (no error, value not stored), so - ; the suite currently aborts 0/0. NEXT: create the #8989.51 def via FileMan - ; (FILE^DIE with the value-type subfield), or seed an existing free-text - ; SYS-settable param with save/restore. See docs/plans/t1.2-vslcfg-design.md. new pass,fail do start^STDASSERT(.pass,.fail) ; @@ -23,40 +25,49 @@ quit ; tSetGetSysPrecedence(pass,fail) ;@TEST "$$set then $$get round-trips a SYS-level value through XPAR precedence" - new key,ien - set key="ZZVSLCFG TEST" - do setup(key,.ien) + new key + do setup(.key) + do true^STDASSERT(.pass,.fail,key'="","a usable XPAR parameter was found") + quit:key="" do set^VSLCFG(key,"hello") do eq^STDASSERT(.pass,.fail,$$get^VSLCFG(key,"MISS"),"hello","SYS precedence read") - do teardown(key,ien) + do teardown(key) quit ; tGetDefaultWhenUnset(pass,fail) ;@TEST "$$get returns the default for a parameter with no value" - new key,ien - set key="ZZVSLCFG TEST" - do setup(key,.ien) + new key + do setup(.key) + quit:key="" do eq^STDASSERT(.pass,.fail,$$get^VSLCFG(key,"fallback"),"fallback","unset returns default") - do teardown(key,ien) + do teardown(key) + quit + ; + ; ---------- fixtures ---------- + ; +setup(key) ; Find a free-text, SYS-settable XPAR parameter currently unset at SYS. + ; Probes empty free-text params (set a sentinel, read it back, restore) and + ; returns the first whose SYS set round-trips. Touches only already-empty + ; params and restores each immediately, so no real config is changed. + new n,i + set DUZ=1,DUZ(0)="@",U="^",DT=$$DT^XLFDT,key="" + set n=$order(^XTV(8989.51,"B","")) + for quit:n=""!(key'="") do + . set i=+$order(^XTV(8989.51,"B",n,0)) + . if i,$extract($get(^XTV(8989.51,i,6)))="F",$$GET^XPAR("SYS",n,1)="" do try(n,.key) + . set n=$order(^XTV(8989.51,"B",n)) quit ; - ; ---------- fixtures (WIP — see header) ---------- - ; -setup(key,ien) ; Create a throwaway free-text PARAMETER DEFINITION (#8989.51). - new hdr - set DUZ=1,DUZ(0)="@",U="^",DT=$$DT^XLFDT - set hdr=$get(^XTV(8989.51,0)) - set ien=$piece(hdr,U,3)+1 - set ^XTV(8989.51,ien,0)=key_U_"VSLCFG test param"_U_U_U_U - set ^XTV(8989.51,ien,6)="F^1:245" - set ^XTV(8989.51,"B",key,ien)="" - set $piece(^XTV(8989.51,0),U,3)=ien - set $piece(^XTV(8989.51,0),U,4)=$piece(hdr,U,4)+1 +try(n,key) ; Sentinel set/read/restore on one candidate; set key on round-trip. + new r + do EN^XPAR("SYS",n,1,"ZZVSLCFGPROBE",.r) + set r=$$GET^XPAR("SYS",n,1) + do EN^XPAR("SYS",n,1,"@") + set:r="ZZVSLCFGPROBE" key=n quit ; -teardown(key,ien) ; Remove the SYS value and the throwaway definition. +teardown(key) ; Restore the chosen parameter's SYS value to unset. new err + quit:key="" set DUZ=1,DUZ(0)="@",U="^" do EN^XPAR("SYS",key,1,"@",.err) - kill ^XTV(8989.51,ien,0),^XTV(8989.51,ien,6),^XTV(8989.51,"B",key,ien) - set:ien $piece(^XTV(8989.51,0),U,3)=ien-1 quit From e1f1aa88d47e31e536fabf390a63970ed3dd2c5f Mon Sep 17 00:00:00 2001 From: Rafael Richards Date: Tue, 16 Jun 2026 04:45:04 -0400 Subject: [PATCH 7/7] T1.2 DONE: VSLCFGTST GREEN 3/3 on both engines (blocker fixed in m-cli) The m test routine-base blocker is fixed (m-cli docker-routines-base d9ee76a: DockerEngine falls back to ${ydb_routines:-$gtmroutines}). VSLCFGTST now 0/0->3/3 on vehu (YDB) and foia-t12 (IRIS --namespace VISTA) via the driver stack, no M_YDB_* host vars. Drop the "blocked" notes from the test header / design note / memory; record the resolution. All engine-free gates + the engine suite green; the three determinism boundaries (re-pin v0.7.0 / check-icr #2263 / citations) stay green. T1.2 complete. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/memory/t1.2-vslcfg.md | 23 ++++++++++++----------- docs/plans/t1.2-vslcfg-design.md | 11 ++++++++++- tests/VSLCFGTST.m | 25 +++++++++---------------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/docs/memory/t1.2-vslcfg.md b/docs/memory/t1.2-vslcfg.md index 4b309a2..8ab5b8c 100644 --- a/docs/memory/t1.2-vslcfg.md +++ b/docs/memory/t1.2-vslcfg.md @@ -1,6 +1,6 @@ --- name: t1.2-vslcfg -description: VSL T1.2 — VSLCFG adapter (binds STDENV config seam to XPAR); adapter done + all 3 gates green; engine suite blocked on an m test routine-base harness gap +description: VSL T1.2 DONE — VSLCFG adapter (binds STDENV config seam to XPAR); all 3 boundaries green + VSLCFGTST 3/3 GREEN on both engines (the m test routine-base blocker was fixed in m-cli) metadata: type: project --- @@ -38,16 +38,17 @@ routines env `v pkg` used (see m-ydb memory `m-ydb-docker-gbldir`): gtmroutines>'`. Then `m vista exec --engine ydb --transport docker ''` sees globals (1211 XPAR defs) AND resolves `$$GET^XPAR`. -**THE REMAINING BLOCKER (engine-bound suite):** `m test --docker vehu` honors -`M_YDB_GBLDIR` (globals visible — gbldir-only assert passes) but **NOT -`M_YDB_ROUTINES`** — it stages routines into a clean `$ZROUTINES` that drops -vehu's resident VistA routines, so `$$GET^XPAR`/`EN^XPAR` don't resolve and -VSLCFGTST aborts **0/0**. The driver's *exec* path (m vista exec / v pkg) layers -the routine base; `m test`'s staging path does not. **Fix = make the m test / m-ydb -test path layer `$ZROUTINES = `** (small, mirrors the -m-ydb `$ZGBLDIR` fix; a **m-cli/m-ydb** session, leaf-first) — or test-in-place via -`m test --resident` against KIDS-installed routines (§12.1). VSLCFGTST is written -and correct; it goes red→green unchanged once XPAR resolves under the harness. +**THE BLOCKER — FIXED in m-cli (2026-06-16).** `m test --docker` uses m-cli's +internal **DockerEngine** (not the m-ydb driver), which exported +`ydb_routines=" $ydb_routines"`. A GT.M VistA (`vehu`) sets +`gtmroutines`, NOT `ydb_routines`, so the export became stageDir-only and (since +GT.M honors `ydb_routines` over `gtmroutines`) vehu's resident XPAR/FileMan +routines vanished → VSLCFGTST aborted **0/0**. Fix = `dockerEnvPrefix` falls back +to `${ydb_routines:-$gtmroutines}` (m-cli `docker-routines-base` `d9ee76a`; see +m-cli memory `docker-routines-gtmroutines-fallback`). **VSLCFGTST now 3/3 GREEN on +vehu (YDB) + foia-t12 (IRIS `--namespace VISTA`)** — no `M_YDB_*` host vars needed; +m-test-engine regression green. The driver *exec* path (m vista exec / v pkg) was +never affected — that uses the m-ydb driver + `M_YDB_*` knobs (a separate path). **Test fixture note:** a hand-built `#8989.51` def (direct global SETs) is NOT enough for `EN^XPAR` to FILE a value (no error, nothing stored) — XPAR's filer diff --git a/docs/plans/t1.2-vslcfg-design.md b/docs/plans/t1.2-vslcfg-design.md index 63f2bfd..ff6da6a 100644 --- a/docs/plans/t1.2-vslcfg-design.md +++ b/docs/plans/t1.2-vslcfg-design.md @@ -167,7 +167,16 @@ Lean: option 1. `m vista exec` runs one command (no dot-blocks over a heredoc), so iterate the FileMan-create logic *inside* the staged test via `m test`, where multi-line M + the STDASSERT report give a real dev loop. -## Status (2026-06-16): adapter DONE + gated; engine suite blocked on a harness gap +## Status (2026-06-16): DONE — VSLCFGTST GREEN 3/3 on BOTH engines + +The harness blocker (below) was **FIXED in m-cli** (`docker-routines-base`, +`d9ee76a`): `DockerRunner` now falls back to `${ydb_routines:-$gtmroutines}` so a +GT.M VistA's resident routines (XPAR) stay on the path. `VSLCFGTST` went +**0/0 → 3/3 GREEN** on `vehu` (YDB) and `foia-t12` (IRIS `--namespace VISTA`) — +no `M_YDB_*` host vars needed. T1.2 is complete (engine suite + all three +boundaries green). The blocker write-up below is retained for the record. + +## Status (historical): adapter DONE + gated; engine suite blocked on a harness gap - **VSLCFG implemented + validated against live XPAR.** `$$get^VSLCFG(key,default)` = `$$GET^XPAR("SYS",key,1)` (SYS-entity read — the faithful analog of STDENV's diff --git a/tests/VSLCFGTST.m b/tests/VSLCFGTST.m index 9e4b0ee..2e7f2ca 100644 --- a/tests/VSLCFGTST.m +++ b/tests/VSLCFGTST.m @@ -1,20 +1,13 @@ VSLCFGTST ; v-stdlib — VSLCFG (XPAR config adapter) test suite. - ; Exercises VSLCFG against a live VistA's XPAR (Parameter Tools). - ; - ; BLOCKED on a toolchain gap (see docs/plans/t1.2-vslcfg-design.md): the - ; `m test --docker vehu` staging path honors M_YDB_GBLDIR (globals visible) - ; but NOT M_YDB_ROUTINES, so vehu's VistA routines (^XPAR, ^XLFDT) are absent - ; from $ZROUTINES and $$GET^XPAR/EN^XPAR do not resolve — the suite aborts - ; 0/0. The harness must layer the engine's resident routine base under the - ; staged routines (mirroring the m-ydb $ZGBLDIR fix), or this runs test-in- - ; place via `m test --resident` against installed routines. The fixture and - ; assertions below are correct and ready once a real engine resolves XPAR. - ; - ; Driver-stack invocation (the ONLY path; m/v waterline): - ; M_YDB_GBLDIR=/home/vehu/g/vehu.gld M_YDB_ROUTINES='' \ - ; m test --engine ydb --docker vehu --chset m \ - ; --routines src --routines /src tests/VSLCFGTST.m - ; (IRIS: --engine iris --docker foia-t12 --namespace VISTA) + ; Exercises VSLCFG against a live VistA's XPAR (Parameter Tools). GREEN 3/3 on + ; BOTH engines via the driver stack (m/v waterline — the ONLY path): + ; m test --engine ydb --docker vehu --chset m \ + ; --routines src --routines /src tests/VSLCFGTST.m + ; m test --engine iris --docker foia-t12 --namespace VISTA \ + ; --routines src --routines /src tests/VSLCFGTST.m + ; (No M_YDB_* host vars needed — the container's `bash -l` env supplies + ; gtmgbldir + gtmroutines once m-cli's DockerEngine layers the resident routine + ; base; see m-cli memory `docker-routines-gtmroutines-fallback`.) new pass,fail do start^STDASSERT(.pass,.fail) ;