Source: external review report, 2026-08-24 (severity: High)
Problem
Screens in the v2 app runtime are string-driven with no existence checks:
src/app.sh:115 — _type=$("${_prefix}_${_current}_type")
src/app.sh:158 — "${_prefix}_${_current}_${_event}"
A typo'd screen name, a handler that forgets to set _SHELLFRAME_APP_NEXT, or an unmapped event yields _current="". The next iteration then invokes PREFIX__type → command-not-found → empty type → case falls through → _rc=0 → nonexistent PREFIX__ handler → loops forever spewing errors. Only SIGINT gets you out.
What it needs
declare -F existence check on the _type function and on the event handler before invoking
- Non-empty assertion on
_SHELLFRAME_APP_NEXT after a handler returns
- A clear diagnostic (
shellframe: unknown screen 'foo' (prefix 'bar')) and a non-zero exit instead of a loop
What it delivers
First-five-minutes robustness for anyone adopting the app runtime — a typo becomes a readable error instead of a runaway process.
Tests
- ptyunit case: app with a handler that never sets NEXT → exits non-zero with diagnostic, no loop
- ptyunit case: transition to a screen with no
_type function → same
Effort: S
Deps: none
Priority: pre-OSS-launch blocker (one of #41/#42/#43/#44)
Source: external review report, 2026-08-24 (severity: High)
Problem
Screens in the v2 app runtime are string-driven with no existence checks:
src/app.sh:115—_type=$("${_prefix}_${_current}_type")src/app.sh:158—"${_prefix}_${_current}_${_event}"A typo'd screen name, a handler that forgets to set
_SHELLFRAME_APP_NEXT, or an unmapped event yields_current="". The next iteration then invokesPREFIX__type→ command-not-found → empty type →casefalls through →_rc=0→ nonexistentPREFIX__handler → loops forever spewing errors. Only SIGINT gets you out.What it needs
declare -Fexistence check on the_typefunction and on the event handler before invoking_SHELLFRAME_APP_NEXTafter a handler returnsshellframe: unknown screen 'foo' (prefix 'bar')) and a non-zero exit instead of a loopWhat it delivers
First-five-minutes robustness for anyone adopting the app runtime — a typo becomes a readable error instead of a runaway process.
Tests
_typefunction → sameEffort: S
Deps: none
Priority: pre-OSS-launch blocker (one of #41/#42/#43/#44)