You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(launcher-standard): reference impls for soft-attach + gui-dialog-chain (#179)
## Summary
The a2ml declared `[soft-attach]` and `[error-visibility]` contracts
but provided no reference implementations. Every downstream launcher
had to re-implement the "if-installed-then-invoke" pattern and the
GUI dialog ladder — guaranteed drift, and a common reason downstream
launchers either skip these features (silent failures stay silent) or
implement them inconsistently.
This adds two sourceable bash helpers in `launcher/`, mirroring the
contract semantics from the a2ml, plus prose with graceful-degradation
usage patterns.
## `launcher/gui-error.sh`
`hp_gui_error "title" "message"`:
| Condition | Behaviour |
|-----------|-----------|
| Always | Write `[title] message` to stderr |
| stderr is TTY or `NO_GUI_ERROR=1` | stderr only, return 0 |
| no `\$DISPLAY` and no `\$WAYLAND_DISPLAY` | return 1 (cannot show GUI)
|
| Else | Try `kdialog → zenity → notify-send → xmessage`; first success
wins |
Mirrors `[error-visibility].gui-dialog-chain` exactly. Verified
locally: `NO_GUI_ERROR=1 ./launcher/gui-error.sh "T" "M"` → stderr
"[T] M", exit 0.
## `launcher/soft-attach.sh`
Three primitives mirroring the three shapes in `[soft-attach].tools`:
\`\`\`bash
hp_soft_attach_present "command" # 0 if on PATH
hp_soft_attach_run "command line" # run if first token present, silent
no-op + 0 if missing
hp_soft_attach_event "tool" "event-name" [args] # `tool emit event-name
args` if present, silent no-op if missing
\`\`\`
All non-fatal — missing tools never break the launcher (per the
§soft-attach spec: *"called if present, silently skipped if absent"*).
CLI mode for ad-hoc use:
\`\`\`
./soft-attach.sh run "hypatia diagnose --app foo"
./soft-attach.sh event feedback-o-tron launcher:start_failed
./soft-attach.sh present hypatia
\`\`\`
## a2ml contract additions
`[error-visibility]`:
- `reference-impl = "launcher/gui-error.sh"` (pointer)
- `suppress-env-var = "NO_GUI_ERROR"` (formalises the override name)
`[soft-attach]`:
- `reference-impl = "launcher/soft-attach.sh"` (pointer)
- Each `tools` entry now carries explicit `style`
(`"event" | "command"`) and `trigger` (e.g. `"on-start-failed"`) so
launchers know **WHEN** to invoke each tool, not just **HOW**.
Previously only `feedback-o-tron` had an explicit failure trigger.
## Prose additions (`launcher-standard.adoc`)
- §Error Handling: rewritten with `hp_gui_error` integration, graceful
degradation pattern, and a NOTE on stderr-always behaviour
- §Soft-Attach (new subsection): documents the three primitives, the
graceful-degradation source pattern, and an example `on_start_failed`
hook wiring all three default tools
## Test plan
- [x] a2ml parses (python tomllib); new fields round-trip cleanly
- [x] Both helpers pass `bash -n`
- [x] `hp_gui_error` writes stderr + respects `NO_GUI_ERROR`
- [x] `hp_soft_attach_present` returns 0/1 correctly
- [x] `hp_soft_attach_run` runs installed, silently skips missing
- [x] `hp_soft_attach_event` silently skips missing tool
- [ ] Manual dialog test (deferred — requires KDE/GNOME desktop;
logic matches well-documented invocation conventions per each
dialog's man page)
- [ ] Lock-step gate (#172) goes green on first push (both files in
diff)
## Coordination
Independent of #170, #171, #172, #173, #175, #176, #177 — no file
overlap. Builds on the resolution ladder shipped in #171
(`hp_resolve_desktop_tools` is referenced in the prose examples) so
the new helpers are findable wherever `.desktop-tools/` resolves.
Both work standalone or via the ladder.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments