Skip to content

vms-01b: HELP — faithful hierarchical-library reader (retire the printf shim + orphaned dead reader) - #449

Merged
baron-3dl merged 3 commits into
mainfrom
vms-01b-help-hierarchical
Aug 13, 2026
Merged

baron-3dl merged 3 commits into
mainfrom
vms-01b-help-hierarchical

Conversation

@baron-3dl

Copy link
Copy Markdown
Contributor

What

Replaces the DCL HELP printf shim and the orphaned, never-dispatched reader with a single shared hierarchical HELP engine that walks a real topic tree parsed from library data — no hardcoded topic content.

Before (origin/main)

  • Live cmd_help (dcl_cmd_misc.c) printed a verb one-liner + 3 hardcoded SHOW/SET/DIRECTORY blocks + a fake one-shot Topic? (no level stack, no Subtopic?, no blank-pops-level, no HELP A B C), and emitted an inauthentic %DCL-W-NOHELP on an unknown topic.
  • A real recursive reader existed (tools/vms_help.cHELP.EXE) but loaded from a compiled-in C string and was orphaned (nothing dispatched it). The honest Sorry, no documentation on X lived only in that dead code.

After

  • src/vmsdcl/dcl_help.c (+ include/dcl/help.h) — parses the documented VMS numbered-level .HLP source format (1 TOPIC / 2 subtopic / 3 ...) into a key/subkey tree and renders:
    • HELP (top-level Information available: listing)
    • HELP topic (topic text + Additional information available: subtopic list)
    • HELP topic subtopic ... (deep lookup, abbreviated keys accepted)
    • the interactive Topic? / <path> Subtopic? loop (blank pops a level, EOF exits)
    • authentic Sorry, no documentation on <x> (not %DCL-W-NOHELP)
    • VMS status codes throughout (SS$_NORMAL / SS$_ITEMNOTFOUND).
  • cmd_help now locates the library (SYS$HELP:HELPLIB.HLP via the logical-name tables, or $OVMX_HELPLIB as a locator override) and drives the shared engine. Honest failure — no fake fallback — if the library is absent (Rule 9 / INV-DCL).
  • tools/vms_help.c (HELP.EXE) — KEPT, because the product-install e2e anti-LARP gate runs the installed image from the target device (tests/qemu/test_product_install_e2e.sh: RUNHELP MOUNT). Its 555-line orphaned reader and compiled-in help string are deleted; it is now a thin wrapper over the same shared engine, reading the real library.
  • distro/Dockerfile.bootable — stages HELPLIB.HLP into the booted image's SYS$HELP (it was never copied; the old HELP.EXE only worked via its compiled-in fallback), so HELP reads real data on a running system.

Clean-room (Rule 8)

The numbered-level .HLP format, the listing headers, the prompt wording, and the not-found message are from public OpenVMS documentation (VSI OpenVMS DCL Dictionary — HELP; User's Manual — "Getting Help") and observed HELP output. The unpublished .HLB binary byte layout is not reproduced; the reader consumes the documented .HLP source form directly, labeled as an OVMX design choice.

Tests

  • tests/dcl/test_help_engine.c (new hermetic ctest dcl-help-engine): top-level listing, topic text + subtopic listing, 3-level lookup, abbreviated keys, unknown topic → Sorry, no documentation on X + SS$_ITEMNOTFOUND (and NOT %DCL-W-NOHELP), and the interactive Topic?/Subtopic? loop.
  • tests/dcl/test_help_content.sh: re-armed for the hierarchical behaviour (grounded in real library content).
  • ctest -LE slow: 158/158 passed, exit 0.

Note / scope decision

The rd item said to delete the orphaned reader. Deleting HELP.EXE outright would break the install-e2e anti-LARP gate that activates the installed image, so instead the dead code (compiled-in string + orphaned duplicate reader) was removed and the file rewired to the shared engine — it is no longer orphaned and no longer carries hardcoded content.

Deferred (still under epic vms-01b)

Compiling .HLP.HLB via LIBRARIAN and HLP$LIBRARY search-list location; per-command help auto-generated from CDU tables; HELP/MESSAGE from the message DB.

🤖 Generated with Claude Code

alice and others added 3 commits August 13, 2026 05:38
…tf shim + the orphaned dead reader)

The live DCL HELP was a printf shim: cmd_help() printed a verb's one-liner
plus three hardcoded SHOW/SET/DIRECTORY blocks and a fake one-shot "Topic?"
with no level stack, no "Subtopic?", no blank-pops-level, no HELP A B C. A
real hierarchical reader existed (tools/vms_help.c, HELP.EXE) but loaded from
a COMPILED-IN C string and was ORPHANED — nothing dispatched it. The honest
"Sorry, no documentation on X" lived only in the dead code; the live path
emitted an inauthentic %DCL-W-NOHELP.

Replace both with ONE shared hierarchical HELP engine that walks a real topic
tree parsed from library DATA (no hardcoded content):

- src/vmsdcl/dcl_help.c (+ include/dcl/help.h): parses the documented VMS
  numbered-level ".HLP" source format (1 TOPIC / 2 subtopic / 3 ...) into a
  key/subkey tree and renders "HELP", "HELP topic", "HELP topic subtopic ...",
  the "Information available:" / "Additional information available:" listings,
  the "Topic?" / "<path> Subtopic?" prompt loop (blank pops a level, EOF
  exits), abbreviated keys, and the authentic "Sorry, no documentation on <x>"
  not-found message. VMS status codes throughout.

- cmd_help (dcl_cmd_misc.c): the printf shim is gone; the built-in locates the
  library (SYS$HELP:HELPLIB.HLP via the logical-name tables, or $OVMX_HELPLIB
  as a locator override) and drives the shared engine. Honest failure — no
  fake fallback — if the library is absent (Rule 9 / INV-DCL).

- tools/vms_help.c (HELP.EXE): kept, because the product-install e2e anti-LARP
  gate runs the INSTALLED image from the target device
  (tests/qemu/test_product_install_e2e.sh). Its 555-line orphaned reader and
  compiled-in help string are DELETED; it is now a thin wrapper over the same
  shared engine, reading the real library.

- distro/Dockerfile.bootable: stage HELPLIB.HLP into the booted image's
  SYS$HELP (it was never copied — the old HELP.EXE only worked via its
  compiled-in fallback), so HELP reads real data on a running system.

Clean-room (Rule 8): the numbered-level .HLP format, the listing headers, the
prompt wording, and the not-found message are from public OpenVMS docs (VSI
OpenVMS DCL Dictionary — HELP; User's Manual — "Getting Help") and observed
HELP output. The unpublished .HLB binary layout is not reproduced; the reader
consumes the documented .HLP source form directly (an OVMX design choice).

Tests:
- tests/dcl/test_help_engine.c (new, hermetic ctest dcl-help-engine): asserts
  top-level listing, topic text + subtopic listing, 3-level lookup, abbreviated
  keys, unknown topic → "Sorry, no documentation on X" + SS$_ITEMNOTFOUND (and
  NOT %DCL-W-NOHELP), and the interactive Topic?/Subtopic? loop.
- tests/dcl/test_help_content.sh: re-armed for the hierarchical behaviour.
- Full ctest -LE slow: 158/158 passed.

Deferred (still under epic vms-01b): compiling .HLP → .HLB via LIBRARIAN and
HLP$LIBRARY search-list location; per-command help auto-generated from CDU
tables; HELP/MESSAGE from the message DB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dcl_help.c is a new vmsdcl translation unit compiled into DCL.EXE, so it must
be listed in the VMS-native LINK.EXE producer graph or the native-link CI jobs
(dcl-native / dcl-native-x86_64, "DCL.EXE VMS-native Link + Activate") go RED
on main push while Debug ctest stays green (Debug never exercises native-link).

- src/vmslink/mk_dcl.sh: add dcl_help to TUS.
- src/imgact/test/run_dcl_native.sh: add dcl_help to TUS; bump the object-count
  guard 23 -> 24.

All CRTL symbols dcl_help.c uses are already exported by DECC$SHR
(mk_decc_shr.sh); the help_* symbols are internal to DCL.EXE. Reproduced the
x86_64 native-link locally in the alpine-musl container exactly as CI does:
"24 DCL objects compiled VMS-native-clean", DCL.EXE linked and activated
through IMGACT.EXE, exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…le prompt sync)

The VMS User Acceptance Test (tests/uat/vms_session_qemu.sh) drives the QEMU
console, where DCL's SYS$INPUT is a TTY. Its run_cmd() sends one command and
hard-waits for the "$ " prompt to return. With the previous cmd_help, "HELP
SHOW" on a TTY entered the interactive "SHOW Subtopic?" prompt loop and never
returned to "$ ", so run_cmd timed out — the UAT went RED (reproduced under a
PTY: HELP SHOW ended at "SHOW Subtopic? ").

Root cause is a behaviour change, not a pinned-old-output test and not a
missing library: the built-in opened the subtopic prompt loop even for a
fully-specified topic. Fix: when a topic is named on the command line, show
that node once (text + "Additional information available:" listing) and return
to the prompt; only bare HELP at a terminal opens the interactive Topic?
browser. This also makes the built-in behave identically to the HELP.EXE image
(which one-shots on args — gated by tests/qemu/test_product_install_e2e.sh).
Opening the subtopic prompt for a specified topic (as VMS does at a terminal)
is a deferred fidelity item under epic vms-01b.

Proven end-to-end: built the bootable image and ran the UAT locally exactly as
CI does (docker run ovmx-boot .../vms_session_qemu.sh) — UAT exit 0, 58/58
checks pass. HELP SHOW reads the real staged SYS$HELP:HELPLIB.HLP (resolved via
the SYS$SYSROOT concealed search-list stat-fallthrough to [SYS0.SYSCOMMON.
SYSHLP]), prints real SHOW help + the subtopic listing, and returns to "$ ".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@baron-3dl
baron-3dl merged commit ce50cc9 into main Aug 13, 2026
61 checks passed
baron-3dl added a commit that referenced this pull request Aug 13, 2026
…456)

Bump OVMX_PRODUCT_VERSION V0.4-1 → V0.4-2. 10 PRs since V0.4-1, toward the
0.5 milestone:

  owns-kernel    #450 OVMX builds its own pinned linux-6.12.103 LTS from source
                 (byte-reproducible, boots 17/17+24/24) — vms-19e beachhead
  self-host #4   #446 MMK.EXE parses descrip.mms + emits TCC→LINK plan
                 (exec-drive facilities, all proven vs real /dev/vms:)
                 #451 lib$spawn real DCL (facade killed) · #452 mailbox IPC
                 #453 write-attention AST · #454 exec-drive design record
  UX fidelity    #447 DIRECTORY format+versions · #448 Ctrl-T status line
                 #449 hierarchical HELP engine · #455 SHOW MEMORY (drop
                 buffers+cached fabrication)
  + swept other threads' merged work

MMK does not yet DRIVE builds (spine #4 needs async AST delivery + IO$M_NOW
+ DCL-mailbox-SYS$INPUT — filed vms-feb/5df/786, faithful path in flight).

Co-authored-by: alice <alice@workspace.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
baron-3dl added a commit that referenced this pull request Aug 13, 2026
Next deferred slice of the HELP facility epic (after #449's hierarchical
.HLP engine): compile a numbered-level .HLP source into a key-indexed
.HLB help library, and locate HELP's library through the HLP$LIBRARY
search list.

LIBRARY/HELP/CREATE lib.HLB src.HLP now compiles the source: a VMS HELP
library is keyed by its level-1 topics, so the compile splits the .HLP
by level-1 keys and writes one module per key into the OVMX "LBRO"
container (dcl/hlb.h), reusing the vms-ca9 LIBRARIAN library
infrastructure. The reader (dcl_help.c help_open_hlb) reads the modules
in index order and reconstructs the exact numbered-level tree, so a
compiled .HLB is indistinguishable from its .HLP source once loaded.
LIBRARY/HELP list/extract keep working on the compiled form.

HELP resolves its library through the documented HLP$LIBRARY,
HLP$LIBRARY_1..n search list (help_open_libraries), each translation
defaulting to .HLB, falling back to SYS$HELP:HELPLIB.HLB then .HLP.
Libraries merge in order so a key in an earlier library wins.

Clean-room (Rule 8): the LIBRARY command, the HELP library-compile
semantics (each level-1 key is a module), and the HLP$LIBRARY search
list are documented (VSI OpenVMS DCL Dictionary: LIBRARY, HELP;
Command Definition, Librarian, and Message Utilities Manual). The
unpublished .HLB byte layout is NOT reproduced -- the LBRO container is
a labeled OVMX design choice.

No facades (INV-DCL): real compile writing a real indexed file, real
search-list resolution, real content lookup. VMS status codes throughout.

Tests: test_help_engine.c gains hermetic .HLB-reader + search-list-merge
coverage (29/29 ok); new tests/dcl/test_help_hlb.sh drives the full DCL
chain (compile two libraries, wire HLP$LIBRARY + HLP$LIBRARY_1, assert
HELP reads the compiled .HLB via each, and first-library precedence for
a shared key). dcl-integration 136/0, dcl-help-engine pass, no #449
regression. Native-link unchanged (no new TU/symbol; NOBJ stays 25; the
three touched TUs compile clean under freestanding musl).

Co-authored-by: alice <alice@workspace.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant