Skip to content

Commit 5632654

Browse files
committed
feat(launcher): E-Grade Launcher Standard conformant launch.sh
Implements the Hyperpolymath E-Grade Launcher Standard (hyperpolymath/standards launcher-standard.adoc/.a2ml) for vsh: - launch.sh: full mode surface --auto/--start/--stop/--status/--browser/ --web/--integ/--disinteg/--help/--version. Version output matches the required 'vsh <version> (<sha>) [<platform>]' format exactly. - Desktop integration (Linux first-class): idempotent --integ/--disinteg, copy-not-symlink launcher, Terminal=true, .desktop at 0444, config+logs preserved on --disinteg. macOS/Windows best-effort. - err()/log(), stderr-always, GUI-error + soft-attach sourced via the published desktop-tools resolution ladder with graceful no-op degradation. - PID/log paths in XDG dirs (never /tmp). - Server-oriented clauses (nohup daemon, wait_for_server URL polling, browser launch) are HONESTLY declared deferred in the a2ml-metadata-block header, since vsh is a foreground terminal shell with no HTTP server. - scripts/run.sh: canonical startup command the standard searches for. - just run / just launch delegate to ./launch.sh --auto. - docs/LAUNCHER.md: conformance attestation + deferred-phase rationale. Verified: --version format, --status, --stop, --auto passthrough, --help, --browser/--web aliases, unknown-mode exit 2, and a full --integ/--disinteg idempotency cycle. shellcheck clean (warning+); bash -n clean. Scope note: full alignment used the public standard fetched from hyperpolymath/standards (that repo is not in this session's GitHub scope). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KfgJznd6jzSeDYsSXGAXkU
1 parent 15c082f commit 5632654

6 files changed

Lines changed: 436 additions & 3 deletions

File tree

CHANGELOG.adoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- Full POSIX shell compliance (subset)
1818
- RMO (Remove-Match-Obliterate) proofs for GDPR compliance
1919

20+
=== Added — 2026-07-17
21+
22+
==== Launcher (E-Grade Launcher Standard)
23+
- `launch.sh` — a standard-conformant launcher implementing the Hyperpolymath
24+
E-Grade Launcher Standard mode surface: `--auto` (default), `--start`,
25+
`--stop`, `--status`, `--browser`/`--web`, `--integ`, `--disinteg`, `--help`,
26+
`--version`. Version output matches the required
27+
`vsh <version> (<sha>) [<platform>]` format. Desktop integration (Linux
28+
first-class) is idempotent, copies rather than symlinks, sets `Terminal=true`,
29+
writes the `.desktop` at 0444, and `--disinteg` preserves config and logs.
30+
Sources `keepopen.sh`/`soft-attach.sh`/`gui-error.sh` via the published
31+
resolution ladder with graceful no-op degradation when the desktop-tools are
32+
absent. PID/log paths use XDG dirs (never `/tmp`). Server-oriented clauses
33+
(nohup daemon, `wait_for_server` URL polling, browser launch) are honestly
34+
**declared deferred** in the `a2ml-metadata-block` header, since `vsh` is a
35+
foreground terminal shell with no HTTP server. See `docs/LAUNCHER.md`.
36+
- `scripts/run.sh` — the canonical startup command the standard searches for
37+
(`{repo-dir}/scripts/run.sh`); builds the release binary on first use and
38+
execs the shell.
39+
- `just run` / `just launch` now delegate to `./launch.sh --auto`.
40+
2041
=== Added — 2026-07-16
2142

2243
==== Launcher

Justfile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ test-cli:
126126
cd impl/rust-cli && cargo test
127127
@echo "✓ Rust CLI tests passed"
128128

129-
# Launch the interactive vsh shell (the primary deliverable). Extra args pass
130-
# through to the binary:
129+
# Launch the interactive vsh shell via the E-Grade launcher (./launch.sh).
130+
# Extra args pass through to the binary:
131131
# just run # start the interactive REPL
132132
# just run --version # print version and exit
133133
# just run script.vsh # run a script
134+
# For the full launcher mode-set (--status/--integ/--disinteg/...), call
135+
# ./launch.sh directly. See docs/LAUNCHER.md.
134136
run *ARGS:
135-
cd impl/rust-cli && cargo run -- {{ARGS}}
137+
@"{{justfile_directory()}}/launch.sh" --auto -- {{ARGS}}
136138

137139
# Build all FFI layers
138140
build-ffi: build-ffi-zig build-ffi-ocaml

QUICKSTART-USER.adoc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,22 @@ cargo build --release # build the release binary
7878
./target/release/vsh --version
7979
----
8080

81+
== Desktop integration (optional)
82+
83+
`launch.sh` is the standard-conformant launcher (E-Grade Launcher Standard). It
84+
adds a desktop menu entry so you can start `vsh` from your application launcher:
85+
86+
[source,bash]
87+
----
88+
./launch.sh --integ # install a desktop entry (Linux; idempotent)
89+
./launch.sh --status # show binary, version, platform
90+
./launch.sh --disinteg # remove it again (keeps your config and logs)
91+
----
92+
93+
`./launch.sh` with no arguments launches the shell (same as `just run`). See
94+
link:docs/LAUNCHER.md[docs/LAUNCHER.md] for the full mode set and conformance
95+
notes.
96+
8197
== Run in a container
8298

8399
[source,bash]

docs/LAUNCHER.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<!--
2+
SPDX-License-Identifier: CC-BY-SA-4.0
3+
Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
4+
-->
5+
# Launcher — `launch.sh` (E-Grade Launcher Standard)
6+
7+
`launch.sh` at the repository root is the single, self-documenting entry point
8+
for running and integrating `vsh`. It conforms to the Hyperpolymath
9+
**E-Grade Launcher Standard** (`hyperpolymath/standards`,
10+
`docs/UX-standards/launcher-standard.adoc` + `launcher/launcher-standard.a2ml`).
11+
12+
```bash
13+
./launch.sh # launch the interactive shell (default --auto)
14+
./launch.sh --version # vsh 0.9.0 (<sha>) [linux-x86_64]
15+
./launch.sh --help # full usage
16+
./launch.sh --status # binary, version, platform, daemon state
17+
./launch.sh --integ # install desktop integration (Linux first-class)
18+
./launch.sh --disinteg # remove integration (keeps config + logs)
19+
```
20+
21+
`just run` / `just launch` delegate to `./launch.sh --auto`.
22+
23+
## Modes
24+
25+
| Mode | Behavior |
26+
|------|----------|
27+
| `--auto` (default) | Build if needed, then launch the interactive shell. |
28+
| `--start` | Alias of `--auto` for a foreground shell (daemon phase deferred). |
29+
| `--stop` | Stop a running daemon if one exists; otherwise a friendly no-op. |
30+
| `--status` | Report binary path, version, platform, and daemon state. |
31+
| `--browser` / `--web` | Aliases of `--auto` (no web endpoint; opens the shell). |
32+
| `--integ` | Install desktop integration; idempotent (`--integ --force` reinstalls). |
33+
| `--disinteg` | Remove integration, preserving `~/.config/vsh` and state/logs. |
34+
| `--help` / `-h` | Usage, modes, file paths, detected platform. |
35+
| `--version` / `-V` | `vsh <version> (<sha>) [<platform>]`, exit 0. |
36+
37+
Arguments after the mode pass through to `vsh`
38+
(`./launch.sh --auto -- path/to/script.vsh`).
39+
40+
## Files
41+
42+
| Path | Role |
43+
|------|------|
44+
| `${XDG_STATE_HOME:-$HOME/.local/state}/vsh/server.log` | Log (never `/tmp`) |
45+
| `${XDG_RUNTIME_DIR:-$TMPDIR:-/tmp}/vsh-server.pid` | PID file (deferred daemon phase) |
46+
| `~/.local/share/applications/vsh.desktop` | Desktop entry (0444, `Terminal=true`) |
47+
| `~/.local/bin/vsh-launcher` | Copied launcher (copy, not symlink) |
48+
49+
## Conformance & honest deferrals
50+
51+
`vsh` is a **foreground terminal shell with no HTTP server or daemon**. The
52+
E-Grade standard is written primarily for web/GUI apps, so a subset of its MUST
53+
clauses do not apply here. Rather than silently skip them, the launcher declares
54+
them **deferred** in its `a2ml-metadata-block` header (`lifecycle-phases-deferred`):
55+
56+
| Standard clause | Status | Rationale |
57+
|-----------------|--------|-----------|
58+
| Universal modes (`--start/--stop/--status/--auto/--browser/--web/--help/--version/--integ/--disinteg`) | ✅ Covered | Implemented and tested. |
59+
| `--version` format `<app> <ver> (<sha>) [<platform>]` | ✅ Covered | Verified exact match. |
60+
| Desktop integration (idempotent, copy-not-symlink, `Terminal=true`, 0444, config/log-preserving `--disinteg`) | ✅ Covered (Linux) | macOS/Windows are best-effort/deferred. |
61+
| `err()`/`log()`, stderr-always, GUI-error + soft-attach via the resolution ladder (graceful no-op if absent) | ✅ Covered | Degrades cleanly when desktop-tools not installed. |
62+
| PID file / logs in XDG dirs (never `/tmp`) | ✅ Covered | Paths wired; used when a daemon exists. |
63+
| `nohup` background server, `wait_for_server()` URL polling, browser launch | ⏸️ **Deferred** | No server/URL — the BEAM daemon is designed but not implemented. `--auto` runs the shell in the terminal, not a browser. |
64+
65+
When the BEAM daemon lands, the deferred server phases (nohup start, URL
66+
readiness, browser open) can be enabled without changing the mode surface.
67+
68+
## Testing
69+
70+
The mode surface is verified manually per change:
71+
72+
```bash
73+
./launch.sh --version # exact format, exit 0
74+
./launch.sh --status # reports state
75+
./launch.sh --integ # installs; second run is idempotent
76+
./launch.sh --disinteg # removes; second run is a no-op
77+
./launch.sh --auto -- --version # passthrough to vsh
78+
```

0 commit comments

Comments
 (0)