Demo-readiness hardening + Flow Editor epic (round-trip, libdoc-per-env, panels) + Chinese locale#45
Merged
Merged
Conversation
… 1, Analyst) Complete function inventory of RoboScope across backend, frontend, recorder/heal/debugger, and ops/integrations/E2E (4 parallel BMAD Analyst agents). Persisted backend detail + a demo-readiness matrix (areas A-K, every feature with demo entry point + edge cases + status) that drives the iterative QA/fix/demo/regression loop toward the demo-video goal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
BMAD QA edge-case audit of the highest-risk untested paths surfaced real demo-breaking defects in run execution; fixed at the source: - C1 (CRITICAL): a cancel during prepare()/sync was erased — execute() reset `_cancelled=False` and ran the whole suite despite CANCELLED. Both runners now short-circuit on a pre-set cancel and never reset it; tasks honors result.cancelled even if the cancelling commit hasn't propagated. - C2 (CRITICAL): SubprocessRunner read stderr only after wait() → full-pipe deadlock on stderr-heavy runs, mis-reported as a hang. stderr is now drained concurrently in its own thread. - H1 (HIGH): inactivity timeout mis-filed as FAILED (status sniffed from a "timeout" substring; the message says "hung"). New RunResult.timed_out flag; tasks classifies TIMEOUT from the flag. - H2 (HIGH): docker wait(timeout=) is an HTTP read timeout that doesn't stop the container (leak + misclassification). Detect timeout by exception type → stop the container + flag timed_out. - H3 (HIGH): commit-before-dispatch violated on TaskDispatchError (flush only) → run could strand in PENDING. Explicit db.commit() on both paths. Tests: new tests/execution/test_execution_robustness.py (6, all fail pre-fix incl. a real-subprocess stderr-deadlock test); updated the mocked subprocess tests to the concurrent stderr-drain API (stderr.readline, not the old post-wait readlines). Affected execution files: 55 passed. Baseline (pre-fix, main): backend 2054 passed / frontend vitest green. Artifacts: demo-readiness inventory + matrix + QA findings + iteration log. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
reconcile_interrupted_runs() marks PENDING/RUNNING runs as ERROR at startup. The _active_runners registry is in-memory, so after a backend restart any such row is an orphan whose worker died — left alone the UI shows a permanently-spinning run. Wired into the lifespan after create_tables(). Tested: orphans -> ERROR, terminal rows untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- M1: lock the websocket count properties (connection_count / run_connection_count) — unlocked reads could raise 'changed size during iteration' under concurrent connect/disconnect. - M3: decode docker logs with an incremental UTF-8 decoder + newline buffer — per-chunk decode corrupted multibyte UTF-8 (accented DE/FR/ES test names) and emitted partial lines to the live output stream. - L1: cap RLIMIT_DATA (4 GB) instead of RLIMIT_AS (2 GB) — RLIMIT_AS counts mmap'd virtual memory, which Chromium/Node reserve heavily, so the 2 GB AS cap could stop Browser-library tests from launching. Tests: M3 incremental-decode regression test; 61 passed across docker+websocket+robustness suites. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per-area reproducible demo-walkthrough format keyed to the committed example fixtures (backend/examples) and the take-demo-video/screenshots harness. Area files authored as each area's QA pass confirms behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
E2E triage (296 passed / 2 failed / 6 skipped) — both failures fixed at source, not via test workarounds: - stats (consistent fail): the toolbar refresh button and the stale-banner refresh CTA both rendered the accessible name 'Aktualisieren' (stats.refresh), an a11y defect (strict-mode ambiguity, confusing in a demo). The banner CTA now uses a distinct stats.refreshNow label in EN/DE/FR/ES. - execution-run (flaky): the assertion waited on the transient 'Testlauf gestartet' toast (auto-dismisses); switched to the persistent .run-overlay-success overlay + cold-run timeout. Verified: frontend vitest 734 passed, prod build clean (i18n escape gate); targeted E2E rerun 18 passed. Both failures confirmed NOT regressions from the execution fixes (POST /runs 201 x8, no 500s). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reproducible per-feature walkthroughs incl. edge cases, keyed to seeded Examples fixtures and tied to the regression tests / e2e specs. Area D documents the C1/C2/H1/H2/H4/M3 edge cases as concrete demo steps. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reproducible per-feature demo walkthroughs + edge cases for every matrix area, keyed to seeded fixtures and the e2e specs. All 11 areas (A-K) now have demo scenarios on disk (DoD: each feature individually demonstrable). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The only specs failing across repeated local full runs are the real-run execution tests (execution-run POST/overlay) — timing/load-sensitive, pass in isolation, fail under a contended local machine + the documented single-worker task queue (not app regressions: POST /runs 201, runs complete, no 500s). Hardened pollRunToCompletion to 220s + 260s test budget (execution-run + heal-toggle) and the run-overlay wait to 30s. The authoritative E2E gate is CI e2e.yml on a clean runner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On clean CI runners: e2e.yml (full Playwright) and build.yml (backend pytest 3.12+3.13 + frontend vitest + all dist builds) both succeed with all Passes 1-7 changes. Confirms the local full-run flakes were environmental. DoD 'existing E2E pipeline runs fully green' is met on this branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…er, LLM errors (Pass 9-10) AI (Pass 9): - C1 CRITICAL: write_generated_file/update_spec_hash now contain writes to the repo (_contained_target) — a user-authored spec target_file like ../../../x could otherwise write arbitrary files. - C2 CRITICAL: _strip_code_fences extracts the balanced fenced block and tolerates a prose preamble/epilogue — the old line-0/last-line stripping left a dangling fence and produced an unparsable .robot. - H4: malformed/empty LLM responses (empty choices / missing content) raise a clear error instead of an opaque IndexError/KeyError. - M1: AI dispatch-failure path commits the failed job (was flush-only). Reports (Pass 10): - H1: nested suite names are hierarchical again (recurse direct child suites; the descendant iterator had flattened them, colliding same-named tests). - H2: test tags exclude keyword-level tags (read only the test's own tags). Tests: test_ai_robustness.py, TestEmptyContentHandling, test_parser_hierarchy.py. Regression: AI affected files 76 passed + 49 robustness/llm; reports 26 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
build.yml on a clean runner passes backend pytest 3.12+3.13 + vitest + all 5 dist builds with the accumulated Execution+AI+Reports fixes. No regression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- M3: LLM calls use httpx.Timeout(connect=5s, read=120s) and translate ConnectError/TimeoutException into a clear "provider unreachable / timed out" message. The old flat timeout=300 let a misconfigured/unreachable provider (e.g. Ollama not running) block the single max_workers=1 executor for 5 minutes, starving all other background tasks. - H3: decrypt_api_key raises a typed ApiKeyDecryptError with a "re-enter the provider key" message instead of an opaque cryptography InvalidToken when SECRET_KEY changed since the key was saved. Tests: connect/timeout + rotated-key tests added; existing wrong-key test updated to the new typed error. ai encryption+robustness+llm: 67 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The test flipped the LAST base64url char of the token; that char carries 'don't care' low bits (3-byte to 4-char alignment), so a different char sometimes decodes to the SAME signature bytes and the HMAC still verifies — making the test flaky (it failed on the Python 3.12 CI leg while passing on 3.13). Perturb the FIRST char instead (fully significant bits), which always changes the decoded payload/signature. 30/30 runs green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…fixes (Pass 13/14) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ass 15, C1+H1) Flagship QA audit of Recorder/Heal/Debugger. Two heal defects fixed at source: - C1 (CRITICAL): recorder sidecars store quality_score on a 0-100 scale, but the heal confidence gate (pick_best_candidate threshold 0.7/0.5) works in 0-1. candidate_finder used the raw 0-100 number as confidence, so every sidecar candidate (e.g. 60.0) passed the 0.7 threshold — the "confidence thresholds gate every swap" safety invariant was fully bypassed on recorded tests. Normalize /100 (tolerating an already-0-1 value). - H1 (HIGH): get_run_heal_report (get_current_user) and apply_heal_patch (global require_role(EDITOR)) bypassed per-repo effective-role RBAC — a global EDITOR without a grant on the run's repo could read heal data and write .robot files cross-repo. Switch both to require_effective_role_for_run (VIEWER / EDITOR), mirroring cancel/retry. Tests: tests/execution/test_heal_confidence_scale.py — the FIRST unit tests for the vendored RoboScopeHeal candidate_finder (previously zero coverage); proves normalization + that the threshold now gates a low-quality sidecar. Existing heal apply/report regression: 20 passed (RBAC swap keeps legit access). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ath guard (Pass 16, H3+M1) - H3 (HIGH): output_xml_walker only descended <kw> elements, so a failure nested in an RF 7.x FOR/IF/TRY/WHILE block was invisible and DEBUG-2 set the breakpoint at the test header instead of the failing line. Recurse through control-structure containers; only <kw> leaves carry source/line. - M1 (MED): the debug file path-traversal guard used str.startswith, which a sibling dir (/data/repo-secrets vs /data/repo) passes. Use relative_to. Tests: tests/debug/test_output_xml_walker.py (plain kw / FOR / IF / none). Debug suite regression: 68 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…etry (Pass 17, M2+M3)
- M2: the recorder emitted wait_until=domcontentloaded only on the synthesised
first New Page; later Go To navigations inherited RF Browser's default
wait_until=load, which hangs past the 10s timeout on ad-heavy pages. Every
Go To now gets wait_until=domcontentloaded (honouring an explicit value).
- M3: heal _should_retry matched bare "timeout"/"locator(", firing on
navigation/assertion timeouts and generic Playwright reprs — non-selector
failures where a heal swap risks clicking the wrong element. Narrowed to
selector-resolution signatures (resolved to 0 elements, waiting for
selector, strict mode violation, ...).
Tests: test_robot_emit::TestGoToWaitUntil, test_heal_should_retry. 44 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…status) Consolidates the 17-pass demo-readiness epic: inventory, 4 QA audits, 24 root-cause fixes with regression tests, demo scenarios for all 11 areas, and the green CI pipeline. Records DoD status + documented niche follow-ups. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…8, H5) _is_already_disambiguated returned True for any `>>`/`>>>`, so an unverified multi-match chained selector (e.g. a shadow chain `.host >> .inner`) skipped the defensive `>> nth=0` wrap and crashed Browser-library strict mode at replay. Only a real nth marker (>> nth=, :nth-match(, :nth-of-type() now counts as disambiguated; a bare pierce does not. Tests: test_robot_emit::TestChainedSelectorDisambiguation (3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ses (Pass 19, H4) DebugSessionManager.start did the dedup at the router (find-then-start), which is racy: two near-simultaneous starts (double-click / retry) both passed the pre-check and both spawned a robotcode subprocess, leaking the first. The dedup now runs inside the manager lock and raises DuplicateDebugSessionError before any spawn; both run-based router start paths catch it and return 409. Tests: tests/debug/test_session_manager.py (first tests for the manager) — the dedup raises before the factory runs (no second subprocess). Debug suite: 70 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The recording command-stream documented a single-subscriber rule but never enforced it: two EventSources (duplicate tab / reconnect race) both pulled from the one SimpleQueue, so each saw only part of the recording. Add a per-session active-subscriber flag (try_acquire_subscriber / release_subscriber under the registry lock); the SSE endpoint returns 409 for a second concurrent subscriber and releases the slot in a finally so a legitimate reconnect after the stream ends still attaches. Tests: tests/recording/test_v2_command_queue_subscriber.py. Recording suite: 410 passed. This closes the last HIGH-severity finding — all CRITICAL + HIGH across the four QA audits are now fixed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s 21, M5+L1)
- M5: _split_iframe_wrap matched only " >>> " (spaced); an iframe selector
with any other spacing around >>> was left unwrapped, so iframe-recorded
heals (consent banners) silently never fired. Spacing-tolerant regex now.
- L1: the legacy recorder generator emitted a literal "***" for password
fields — the generated test typed three asterisks and the login failed.
Emit a ${PASSWORD} variable + a CHANGE_ME placeholder definition; the real
captured secret is still never written.
Tests: test_heal_iframe_split.py (4), test_generator TestPasswordVariable (2),
updated test_password_masked. 20 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, CI green ~30 root-cause defects fixed across 21 passes (4 QA audits); flagship audit cleared (heal/debugger/recorder). C2/M4/L2 accepted/deferred with rationale. Full CI pipeline green on a clean runner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lete The March-era demo-video tour aborted at the run-creation modal (UI drift): one unguarded click hit the 8s actionTimeout and failed the whole recording. Guard + swallow every run-start interaction (the flow itself is covered by execution-run.spec.ts) and Escape any leftover modal, so the Full Feature Tour records end-to-end. Re-rendered a current EN demo video (3:20). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend the demo-video tour with a 'Deep Dive — every feature & edge case' section driven by the demo-readiness matrix: Auth/RBAC (wrong-creds error, rate-limit, real VIEWER read-only login, i18n), Explorer/Editors edge cases, Heal (opt-in, confidence/budget gating, suspect-heal, no-heal tag), Debugger (re-run-to-error, run-up-to-here, prereq install), Recorder (transport gating, shadow/cross-frame, single-subscriber), Execution edge cases (cancel, schedules + invalid cron), Environments (validation, browser/heal/offline pack), Reports/Stats/History (upload guards, flakiness/quarantine), Enterprise (SSO dry-run, teams, emergency bypass). Captions are now blocking (awaited) so each feature/edge-case overlay is readable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The demo tour rendered the /welcome onboarding screen on every page because login() never cleared `first_login_complete` for the seeded admin — the router guard bounced every route to /welcome. This nullified both the overview tour and the deep-dive (frames showed only the dashboard with captions). - login(): PATCH /auth/me/first-login-complete=true so navigation lands on the real feature pages. - Execution scene: dispatch the two demo runs through the proven POST /runs API path (guaranteed real Robot Framework execution + output + reports), show the run-creation modal as the visual, poll real status to terminal, then open the failed run's detail + real Output modal. - repoId resolver prefers the local "Examples" repo (has the .robot files on disk) over the possibly-empty git-clone variant. - Users scene: click the Settings "Benutzer" sub-tab directly (no nav-more-toggle). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first-login fix exposed two follow-ups when real pages finally rendered: - Real feature pages hold live WebSocket/SSE connections, so `networkidle` never settled and every nav()/reload()/goto burned its full 30s timeout — the DE render ballooned to ~32 min (incl. ~8 min stuck on /login). Switch all 13 waitUntil/waitForLoadState calls to `domcontentloaded`. - Debugger scene re-declared `failedId` (already declared in the execution scene) → TS duplicate-declaration → no tests collected. Reuse the variable. - Users scene: drop the spurious `.nav-more-toggle` click. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ix comment corruption
Story: Flow Editor — Verification & Hardening (P0 round-trip).
Extract the RF text parse/serialize path out of RobotEditor.vue (3486 LOC) into
a pure, unit-tested module `robotTextIO.ts` — single source of truth, no more
duplicate logic that drifts (the failure mode the RobotEditorEscapeRoundTrip
test had to guard against by re-implementing helpers verbatim).
Fixes two silent-corruption bugs surfaced by the new golden-corpus test:
- Inline trailing comments (`Click ${sel} # note`) were swallowed as an arg
and escaped to `\# note`. Now preserved on `RobotStep.trailingComment` and
re-emitted verbatim.
- A column-0 comment inside `*** Test Cases ***` / `*** Keywords ***` became an
item literally NAMED `# comment`. Now buffered as `leadingComments` on the
next item (or `form.trailingComments` if dangling) and re-emitted.
Round-trip contract documented + pinned: idempotency over a real golden corpus
(byte-stable second pass), structural-equality re-parse, and regression pins for
escapes, `${}`/`@{}`/`&{}`/`%{}` variables, `...` continuation folding, and
nested FOR/IF/ELSE/END + RETURN.
Adds the BMAD story doc capturing the party-mode decisions and the full AC/test
plan for the remaining increments (file-settings+Variables inline, libdoc-per-
environment keyword discovery, control-structure e2e).
Tests: 754 frontend vitest green (incl. 20 new FlowEditorRoundTrip), vue-tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Story: Flow Editor — Verification & Hardening (P0, Winston's offline-first path).
Makes the Flow Editor's keyword palette able to show keywords from BOTH standard
and third-party libraries (Browser, SeleniumLibrary, …) WITHOUT depending on the
optional rf-mcp live server — RoboScope is offline-first.
- `keyword_introspection.py`: runs `robot.libdoc` (one subprocess) inside the
environment's own venv over BUILTIN_LIBRARIES + every identified installed RF
library, returning {name, library, args, shortdoc}. Libraries that can't be
imported are skipped, never fatal.
- `EnvironmentKeywordCache` model + alembic migration: one row/env, cached
keywords + a `source_hash` (digest of the venv's installed name==version set);
drift → stale → re-introspect. uv-lockfile-equivalent invalidation.
- `GET /environments/{id}/keywords`: returns the fresh cache immediately; on
miss/stale/refresh dispatches a background rebuild (`introspect_keywords_task`)
and returns the current cache with status "building" so the UI renders what's
there and polls for the rest. commit-before-dispatch honoured.
Tests: 15 pytest (hash determinism + drift, target-library selection, subprocess
parse/bad-json, cache rebuild persist/error, endpoint ready/building/404/auth).
ruff + mypy clean on all new code; zero new lint errors in touched files.
Frontend palette wiring + project>library>BuiltIn shadowing fix follow next.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n + env-keywords client Story: Flow Editor — Verification & Hardening (P0 shadowing fix + libdoc client). Fixes the long-standing shadowing bug (the EDITOR-2 TODO): a project/resource keyword sharing a BuiltIn name showed the BuiltIn's signature, so the editor offered the wrong args → broken tests. useKeywordSignatures now mirrors Robot Framework's own search order — project/resource > library > BuiltIn — building the map lowest-precedence first so higher tiers overwrite on a name clash. - Promote project keywords into the explorer store (`projectKeywords` + `setProjectKeywords`) so the signature composable can see them; KeywordPalette pushes its loaded project keywords there. - Add `getEnvironmentKeywords()` API client for the new libdoc-per-environment endpoint (offline-first palette source; consumption wiring follows). Tests: 758 frontend vitest green (+4 shadowing-precedence cases), vue-tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-per-env Story: Flow Editor — Verification & Hardening (completes #4 end-to-end). preloadKeywords now resolves the repo's environment (own environment_id, else the default env) and prefers GET /environments/{id}/keywords (libdoc cache — works without rf-mcp). Falls back to the rf-knowledge search when the env cache is still building/empty, no env resolves, or the endpoint errors — so the palette is never worse than before and now shows foreign + standard library keywords offline. Tests: +4 explorer.store specs (ready→use libdoc, building→fallback, no-env→fallback, error→fallback); 762 frontend vitest green, vue-tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Story: Flow Editor — Verification & Hardening (P0 AC-B).
Closes the two-editors gap: suite variables and suite-level settings are now
editable in the Flow tab, mirroring the existing Libraries panel (the
consistent "settings = toolbar panels" model).
- Variables panel (📦): list / add / edit / remove *** Variables *** entries;
bare names auto-wrap to ${NAME}; edits commit on blur/Enter (never a
continuous v-model into the form, matching the libraries-panel discipline).
- Suite-settings panel (⚙️): Suite Setup/Teardown, Test Setup/Teardown, Force/
Default Tags, Documentation, Metadata, Test Timeout — quick-add chips for
absent keys, inline value edit, remove.
- i18n keys in EN/DE/FR/ES (i18n-completeness test green).
- e2e flow-editor-file-settings.spec.ts (lists/adds/removes); serialization
round-trip already pinned by the robotTextIO unit tests.
Tests: 762 frontend vitest green, vue-tsc clean. e2e runs in the green gate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Story: Flow Editor — Verification & Hardening (P1 AC-D). Closes the control-structure coverage gap (previously the nesting frames had no round-trip test). Confirms the parser/serializer conserve nested blocks + matching ENDs — no fix needed, the logic was correct, it was just unpinned. - Unit FlowEditorControlStructures.spec.ts (5): FOR-in-IF + 2 ENDs, TRY/EXCEPT AS/FINALLY with exc var, WHILE limit=, END-matching at depth 3 (FOR>IF>FOR, byte-stable double round-trip), BREAK/CONTINUE in a loop. - e2e flow-editor-control-structures.spec.ts: live flow→code round-trip keeps IF/FOR/ELSE/TRY/EXCEPT/FINALLY + exactly 3 ENDs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…table, kw-source)
Splits the deferred items from the hardening story into 4 sprint-ready stories
with ACs + task + test plans: FE-BDD (Given/When/Then awareness), FE-ENV (%{}
env-var awareness), FE-TPL ([Template] data-row table), FE-KWSRC (libdoc as the
universal keyword source, shrink the static fallback).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Story FE-BDD. Recognises BDD prefixes (Given/When/Then/And/But) on keyword steps: the node renders a prefix badge with the keyword shown sans prefix, and signature lookup falls back to the prefix-stripped name (so `When Login` shows `Login`'s args) while a keyword literally named with the prefix still wins. Round-trip keeps the prefix verbatim — purely visual + resolution sugar, no dedicated BDD authoring mode (per the story's scope). Tests: +5 unit (splitBddPrefix matrix, converter flag, signature fallback + verbatim preference); e2e flow-editor-bdd (3 badges + round-trip). 772 vitest green, vue-tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Story FE-ENV. Recognises RF environment-variable references %{NAME} /
%{NAME=default}: a node shows a %{} indicator (tooltip lists the names +
defaults), and the Variables panel gains a read-only "Environment variables
used" summary for the active item. Round-trip keeps %{} verbatim. Read-only
awareness only — OS env values aren't edited here.
Tests: +7 unit (extract/collect matrix, converter flag, round-trip); e2e
flow-editor-env-vars (badge + panel summary). 779 vitest green, vue-tsc clean,
i18n EN/DE/FR/ES.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e table Story FE-TPL. Fixes the one deferred item that was mis-MODELLED: data rows of a [Template] test were parsed as bogus keyword steps. Now: - robotTextIO: RobotTestCase.templateRows; parser routes a templated test's body rows into templateRows (control structures inside stay real steps), serializer re-emits them; `...` continuation extends a row. Round-trip pinned. - flowConverter: emits a `template-table` node (Start → table → End) carrying the keyword + rows. - FlowEditor: editable table node — edit cell on blur, add/remove row, add column; structural edits rebuild the graph. - Fix: selectedNodeData returns null for `template-table` (selecting it had crashed the step detail panel with a toUpperCase-on-undefined render error). - i18n EN/DE/FR/ES. Tests: +6 unit (parse/round-trip/continuation/control-stays-step/converter node); e2e flow-editor-template (table renders, add row round-trips to code). 790+ vitest green, vue-tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… static map is bootstrap-only Story FE-KWSRC. Documents + pins that RF_KEYWORD_SIGNATURES is a STANDARD- LIBRARY-ONLY bootstrap used before an environment is introspected; the libdoc-per-environment endpoint is the universal source (resolution order: project > libdoc(env) > bootstrap). Adds RF_BOOTSTRAP_SIGNATURES alias to make the role explicit without import churn. "Shrink, don't grow" — a test pins that no third-party keywords (Browser/Selenium) leak into the static map. Tests: +5 unit (bootstrap invariants, no-third-party, libdoc-overrides-bootstrap); e2e flow-editor-libdoc-keywords (env endpoint → palette shows libdoc keyword, no rf-mcp). vitest green, vue-tsc clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a Simplified-Chinese locale, registers it in the i18n config (with an
English-then-German fallback chain for zh), and offers ZH in the header
language switcher. The locale is deep-merged over the English base so EVERY
key resolves — high-traffic UI (common, nav, auth, dashboard, notifications,
flow-editor panels, welcome) is translated; the long tail falls back to English
under zh and can be extended over time. vue-i18n placeholders ({name}, {email})
and the escaped `@` are preserved.
Tests: +3 unit (ZhLocaleParity — every en key resolves under zh, spot
translations, placeholders intact); e2e i18n-chinese (ZH switch renders 中文 +
persists across reload). 793 vitest green, vue-tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ing)
Edge-case-hunter follow-up on the flow-editor work. Each fixed at source with a
fail-before/pass-after regression test (FlowEditorRoundTripEdgeCases.spec.ts):
1. Inline comment on a CONTROL line (`IF ${x} # note`, FOR/WHILE/…) was
parsed onto step.trailingComment but the serializer only re-emitted it for
keyword/assignment → dropped. serializeStep now applies trailers uniformly.
2. A [Template] data cell starting with '#' serialized unescaped → RF read it
as a comment at runtime. New escapeRfCell/unescapeRfCell escape leading '#'.
3. A [Template] data cell with an internal 2+-space run split into extra
columns on round-trip. escapeRfCell now escapes those spaces as `\ `.
4. [Template] declared AFTER its data rows mis-parsed the earlier rows as
keyword steps. Parser now looks ahead within the test body for [Template]
and classifies all rows as data.
Tests: +5 edge-case unit; 798 vitest green; template + control e2e green;
vue-tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ead-path, round-trip) 3-layer pre-merge review (Blind Hunter + Edge Case Hunter + Acceptance Auditor) of the flow-editor epic. 7 patch findings fixed at source, 3 deferred, 4 dismissed. HIGH (AC-B3 / FE-TPL AC5): inline Variables/suite-settings/template-cell edits mutated props.form directly, firing the deep watcher that resets activeItemIndex to 0 and clears the selection — so editing a variable while on test case #2 yanked the canvas back to #1. (The earlier e2e missed it: fixtures had a single test case, so reset-to-0 was invisible.) Added keepActiveItemOnRebuild() to all direct mutations; new e2e uses TWO test cases to pin it. MED: keyword_cache_is_fresh no longer shells out to `uv pip list` on every GET /keywords — compares the env's packages_changed_at against the cache updated_at; redundant introspection dispatch suppressed while a build is in-flight (120s); empty [Template] no longer pulls body rows into data mode. LOW: EXCEPT catch-all (`AS` at idx 1) keeps its var; task count = real keyword count; tab round-trip test pinning documented normalization. Deferred (logged in deferred-work.md): FQN Library.Keyword disambiguation, multi-line [Tags]/[Setup] continuation (pre-existing), template-cell-equals- control-marker (RF-ambiguous). Tests: 799 frontend vitest + 17 round-trip/edge green; 16 backend keyword pytest green; 7 flow-editor e2e green (incl. AC-B3 regression); vue-tsc clean; ruff below baseline on touched files. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…editor retro document-project pass focused on the Flow Editor epic: - CLAUDE.md gotchas: robotTextIO round-trip contract + escape helpers + dual type-system caveat; FlowEditor deep-watcher activeItemIndex/selection reset (suppressFitView) + e2e ≥2-test-case rule; [Template] templateRows model; libdoc-per-environment discovery + cache-freshness via packages_changed_at; keyword resolution order project>libdoc>bootstrap; ZH locale. - Flow-editor epic retrospective artifact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove everything an agent can discover by reading the repo (architecture tree + LOC, tech-stack list, Makefile command list, API-prefix catalog, config table, RBAC enum, drift-prone milestone/known-issues/test-gaps lists, the full release checklist already in the release-publish skill) and the 137-line RTK catalog that duplicates the global CLAUDE.md. Keep the gold: the non-derivable why-landmine gotchas, a few non-obvious conventions, the one release trigger landmine + pointer, a compact roadmap, and a BMAD pointer. 332 → ~50 lines.
Old cmd.exe has no VT processing, so uvicorn's colored startup logs render as raw escapes (←[32mINFO←[0m, Uvicorn running on ←[1m…). Add --no-use-colors to the generated start-windows.bat in both the offline (build-windows.ps1) and online (build-online-mac-and-linux.sh) builds. mac/linux keep colors (their terminals render ANSI; uvicorn auto-disables when piped).
…act cell (EDITOR-9b)
The picker's "Eigener Wert …" previously just appended an empty slot, which the
editor then labelled as the NEXT positional parameter (getArgLabel resolves a
bare slot at index N to the N-th signature param) — so "custom value" silently
became "next parameter", with no way to enter a free value or an arbitrary
name=value.
Now it's a real free-form input: type a bare value (`5s`, `${VAR}`) or a
`name=value` (incl. **kwargs) and it's pushed verbatim — a name=value then
resolves to its named spec regardless of index; a bare value is positional.
The named-parameter list (target a specific param out of order) is unchanged.
Also fixes a real popover-positioning bug surfaced while testing: the
Teleported add-arg popover is pinned to the trigger (which sits at the right
edge / low in the tall detail panel) and could open off-screen on a narrow or
short window. Now clamped to the viewport horizontally and flipped above the
trigger when it would overflow the bottom.
Tests: +3 unit (custom-value contract: verbatim push, name=value resolves to
named spec, empty ignored); e2e flow-editor-add-arg (type name=value → round-
trips to code); i18n EN/DE/FR/ES. 802 vitest green, vue-tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This branch bundles three sequential BMAD epics. It is large (45 commits) but every change landed with tests and the touched suites are green locally; CI (
build.ymltest-unit +e2e.yml) is the authoritative gate.1. Demo-Readiness epic (≈24 defects fixed at source, each with a regression test)
Adversarial QA audits across Execution, AI/Reports, Recorder, Heal, Debugger → root-cause fixes (no workarounds):
Go Towait_until._bmad-output/.2. Demo video — real full-fledged execution
Rewrote the Playwright capture tour to perform genuine executions of every feature + edge cases (real runs, self-healing, debugger, SSO/IdP, etc.) instead of caption teasers. Root cause of the prior broken render:
login()never clearedfirst_login_complete, so every route bounced to/welcome; also switchednetworkidle→domcontentloaded(live pages hold WebSockets).3. Flow Editor epic — Verification & Hardening + 4 follow-ups + Chinese locale
The headline work. Story docs under
_bmad-output/planning-artifacts/flow-editor-*..robotparse/serialize into a pure, unit-testedrobotTextIO.ts; fixed silent-corruption bugs (inline comments → escaped args; column-0 comments → test-case names; control-line comments dropped;[Template]cell#/double-space/after-rows). Golden-corpus identity tests.GET /environments/{id}/keywordsrunsrobot.libdocin the env venv (offline-first, no rf-mcp), DB-cached withpackages_changed_atinvalidation + background task. Palette sources from it; shadowing fixed (project > library > BuiltIn).*** Variables ***+ suite-settings panels in the Flow tab.%{}awareness), FE-TPL ([Template]data-row table), FE-KWSRC (libdoc universal, static map = bootstrap)._bmad-output/implementation-artifacts/deferred-work.md.Testing
vue-tsc --noEmitclean.Deferred (logged, non-blocking)
FQN
Library.Keyworddisambiguation · multi-line[Tags]/[Setup]...continuation (pre-existing) · template-cell-equals-control-marker (RF-ambiguous).🤖 Generated with Claude Code