Skip to content

Release 0.12.0 — Epic EXEC (RF execution config) + curated modifiers/listeners + Settings UX#57

Open
raffelino wants to merge 11 commits into
mainfrom
feat/exec-10-11-curated-modifiers-listeners
Open

Release 0.12.0 — Epic EXEC (RF execution config) + curated modifiers/listeners + Settings UX#57
raffelino wants to merge 11 commits into
mainfrom
feat/exec-10-11-curated-modifiers-listeners

Conversation

@raffelino

Copy link
Copy Markdown
Collaborator

Cuts 0.12.0. Brings the full Epic EXEC (RF execution configuration, stories EXEC.1–11), plus a set of Settings UX/i18n fixes.

Highlights

Epic EXEC — RF execution configuration (EXEC.1–9)

  • Single resolver seam (ResolvedRunSpec) + runner parity; three-zone arg safety (output-owning + code-loading flags always rejected, incl. short aliases & abbreviations; args as list, never a shell).
  • Governed Advanced run section (variables + freeform args, EDITOR + executionAdvancedArgs), audited.
  • Tag discovery pick-list; read-only long-name/structural-id; __init__.robot editor constraint; DataDriver (flag-gated).

Curated & org-extensible modifiers + listeners (EXEC.10–11)

  • Modifier/listener registry with three trust tiers: vendor (in-repo), organization (via roboscope.modifiers entry-point or ROBOSCOPE_MODIFIERS_CONFIG — backend config, no UI), and admin-gated runtime user-code.
  • Pre-run / post-run (--prerebotmodifier) modifiers + live listeners — the hook to push results to a TMS / emit custom reports — without ever exposing a free-typed code-loading flag.
  • Repo-confined, admin-only --pythonpath / --variablefile levers behind explicit consent.
  • Full in-app docs (EN/DE/FR/ES).

Settings — clarity & safety

  • Sticky unsaved-changes bar (row markers, Discard, leave guard) on the General tab.
  • Feature-flag toggles take effect immediately (no hard reload); EXEC flags surfaced as toggles (default off).
  • All settings descriptions + category headers localized (EN/DE/FR/ES/ZH).

Review & verification

  • Each story ran the full BMAD cycle: dev-story → bmad-code-review (3 adversarial reviewers) → fixes. Hard security invariant (deny-list absolute & role-independent) verified intact across EXEC.10/11.
  • Release-readiness: backend full suite (2249 passed), frontend unit (870), prod build (Gate 1), i18n/doc gates (Gate 8), e2e (settings unsaved-changes) — all green. (4 transient local failures traced to a stale local dev DB missing the EXEC.2 columns — not a code regression; CI uses a fresh DB.)

🤖 Generated with Claude Code

raffelino and others added 11 commits June 24, 2026 10:55
Implements the EXEC epic — resolver seam + ResolvedRunSpec, runner parity,
advanced-config persistence + per-lever GOV flags (default-OFF), advanced
args/variables UI, tag discovery, long-name/id surfacing, __init__.robot
editor constraint, PreRunModifier channel, and DataDriver (flag-gated).

Includes the whole-epic code-review fixes (2026-06-24):
- HIGH: Z3 deny-list hardened — short aliases, --variablefile/--argumentfile,
  and unambiguous long-option abbreviations now rejected (NFR1).
- Audit records the resolved argv + modifiers as a structured payload.
- Tag parser uses RF-correct separators (tab/2+ spaces), Settings-scoped,
  null-path guarded; parseArgs is quote-aware; init-file detection wired to
  the tested helper + round-trip pinning spec.
- Gate-order doc corrected to match the safer implemented flag->role->deny.

Docs: in-app "Advanced Run Configuration" section (EN/DE/FR/ES) + CLAUDE.md
EXEC invariants. Drafts EXEC.10 (curated/org-extensible modifiers + code
levers) and EXEC.11 (custom listeners) as follow-ups.

Backend 377 exec/gov/explorer tests green; frontend init-file spec + i18n
parity + vue-tsc clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
…code levers

Adds a curated modifier registry with three trust tiers (vendor in-repo /
org-deployed via roboscope.modifiers entry-point + ROBOSCOPE_MODIFIERS_CONFIG /
runtime user-code), pre- and post-execution channels (--prerunmodifier /
--prerebotmodifier — the latter the results→TMS/report hook), and repo-confined
--pythonpath / --variablefile levers. All are separate typed channels on
ResolvedRunSpec; the Z3 deny-list stays absolute and role-independent.

Gate routes curated-vs-user-code by registry membership (not spoofable: curated
keys resolve to their registry class path server-side). New ADMIN-only default-OFF
flags executionPythonPath/executionVariableFile; repo-confinement enforced at both
request time (gate, 422) and execution (resolver). Audit records resolved class
path + tier + consent. Frontend: registry-key pickers + server-enforced consent
for the code-loading levers; i18n x5; in-app docs subsection x4 locales.

Code-review (3 adversarial reviewers): hard invariant intact; 11 fixes applied
(server-side consent, curated-key-vanished crash guard, docker FLAKY-3 drop,
kind-mismatch/colon-arg/non-list 422s, /modifiers flag gate, role-ValueError
guard, registry cache lock, startup warm-load).

405 exec/gov/explorer backend tests + 16 frontend tests green; vue-tsc + ruff +
Gate-8 clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
…ible)

Extends the EXEC.10 modifier registry with a `listener` kind: custom Robot
Framework listeners (live per-event callbacks) selectable via the registry
(vendor/org trust tiers) or as ADMIN + executionCustomListenerUserCode + consent
user-code. Emitted via the existing ResolvedRunSpec.listeners channel and merged
AFTER the system quarantine listener (system-first, additive, de-duplicated) so a
user listener can never drop or reorder the system ones. Free-typed --listener
stays denied in the Z3 field.

Ships a Tier-A vendor LiveProgressListener; the loader validates a listener-kind
class declares a valid ROBOT_LISTENER_API_VERSION (v2/v3) or skips it. Gate reuses
the kind-match + colon-arg + consent guards; audit records resolved listener class
path + tier. Frontend listener picker group; i18n x5; in-app docs extended (4
locales) with the live-vs-post-run distinction.

Code-review (3 adversarial reviewers): hard invariant intact (deny-list absolute;
system listeners never clobbered — pinned); 4 fixes applied (v2/v3 validation,
merge de-dup, format-string robustness, comment accuracy).

418 exec/gov/explorer backend tests + frontend tests green; vue-tsc + ruff + Gate-8 clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
The EXEC advanced-execution flags (executionAdvancedArgs, the two user-code
flags, pythonpath/variablefile, datadriver) were registered in FEATURE_FLAGS
but never seeded as features.* settings rows — so they had no Settings UI
toggle and could only be enabled via ENV var. Seed them (all default false,
idempotent insert-if-missing) so admins can turn them on in Settings → Features.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
Settings → Features rendered each setting's English DB description verbatim, so
the descriptions were always English regardless of UI language. Add a localized
`settings.descriptions.*` lookup (keyed by a stable camelCase id, falling back
to the DB string for untranslated settings) covering packageManagement, its role
floors, and the EXEC advanced-execution flags, in all 5 locales.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
…(5 locales)

Two fixes:
1. Toggling a feature flag in Settings did not take effect until a hard page
   reload — useFeatureFlags caches the flag set once and saveSettings never
   refreshed it. saveSettings() now calls refresh() when a features.* setting
   changed, so e.g. enabling executionAdvancedArgs surfaces the run dialog's
   Advanced section immediately.
2. Extend the localized-description mechanism to ALL settings (not just the
   EXEC feature flags): category headers (settings.categories.*) and every
   default setting's description (settings.descriptions.*) are now translated
   in EN/DE/FR/ES/ZH, with a fallback to the English DB string for any future
   untranslated setting.

vue-tsc + i18n parity green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
…uard

The General settings tab stacks 8 category cards above a single Save button far
below the fold, so users edited settings without noticing they hadn't saved.

- Dirty tracking: compare editedValues against a saved baseline (set on load and
  after each successful save).
- Sticky 'N unsaved changes' bar pinned to the viewport bottom (appears only when
  dirty) with Discard + Save — always in view regardless of scroll.
- Per-row marker: an accent rail + dot on each changed setting.
- Bottom Save button disabled when there are no changes.
- Safety net: onBeforeRouteLeave + beforeunload prompt when leaving with unsaved
  changes.
- i18n settings.unsaved.* in all 5 locales (pluralized count).

vue-tsc + i18n parity green; pluralization render-checked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
Playwright spec for the sticky unsaved-changes bar: appears on edit with a row
marker + count, Discard reverts without persisting, Save persists + clears (and
survives reload), and the in-app route-leave guard prompts (dismiss stays, accept
navigates). Adds data-testids (unsaved-bar/count/discard/save) for stable,
locale-neutral targeting. 3/3 green against the live stack.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
Bump version to 0.12.0 across frontend/package.json (+lock), backend/pyproject.toml
(+uv.lock); add the 0.12.0 CHANGELOG entry covering Epic EXEC (RF execution
configuration, EXEC.1-11), curated/org-extensible modifiers + listeners, and the
Settings UX/i18n improvements.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
…on fix)

Localizing the General-tab category headers means the 'general' category now
renders as a 'Allgemein' card — colliding with the 'Allgemein' tab label, so the
bare getByText('Allgemein') hit 2 elements (strict-mode violation). Target the
.tab buttons instead. 13/13 settings specs green locally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QE7VMgyAn24d3H1pMK2Dc
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