# MC-4292: Wire Tessa as user tester (second Reviewer stage) **Priority:** medium **Assigned:** luci **Depends on:** MC-4291 (the review loop must exist first) ## What to do ...
StateDoneNext ActionClosedOwnerLuciRuntimeClosedAge17d ago
Ticket is done; runtime is closed.·profile claude_opus_1m_medium · cwd /home/lucienne/workspace/mission-control · uptime 16d 18h · last activity 16d 14h ago
Description
MC-4303
# MC-4292: Wire Tessa as user tester (second Reviewer stage)
**Priority:** medium
**Assigned:** luci
**Depends on:** MC-4291 (the review loop must exist first)
## What to do
After the QA reviewer passes, Tessa should run a browser-based user test before the ticket is considered done. Tessa catches things the QA reviewer can't — visual bugs, broken UX, mobile issues.
## Steps
1. **Add a Tessa dispatch trigger.** After the QA reviewer verdict is `pass` AND the ticket involves UI changes (detect by checking if the diff touches `.html`, `.css`, `.js`, template files, or if the ticket has a `ui` tag), dispatch Tessa.
2. **Tessa dispatch mechanism.** Use the existing Tessa agent pattern:
- If Tessa is available as a runtime profile or MC worker, dispatch via `mc_pickup.py` with a prompt that includes: the ticket description, the files changed, the QA reviewer's verdict, and the `done_sha`
- Tessa opens a browser, walks the user journey, takes desktop + mobile screenshots, and returns APPROVED or an issue list
- If no Tessa runtime is configured yet, skip Tessa for now and add a comment: "Tessa not yet wired — QA reviewer passed but no browser test. Manual test recommended."
3. **If Tessa says APPROVED** → proceed to the "gate to Elmar" check (MC-4291 already handles this).
4. **If Tessa returns issues** → add a comment with the issue list and screenshots, set ticket back to `todo`, increment `review_cycles`, re-dispatch to Worker (same as MC-4291 QA-fail path).
5. **Track Tessa results.** Add a `tessa_verdict` column or use the existing evidence/comment system to record: `APPROVED` / `ISSUES` with the issue list.
6. **Commit and push.**
## Acceptance criteria
- UI-touching tickets trigger Tessa after QA passes
- Tessa's verdict is recorded in the ticket evidence
- Tessa failure sends the ticket back to the Worker (same loop as QA fail)
- Non-UI tickets skip Tessa without error
- If Tessa is not available, the ticket proceeds with a warning comment
## If blocked
- If no Tessa runtime exists on Luci, this ticket becomes: "Configure Tessa as an MC runtime profile, then wire the dispatch." Check if Tessa already exists as a runtime in `runtime_sessions` or as a separate tmux session.
- If browser testing requires headed Chrome and Luci's VNC setup is broken, flag as blocker and skip — the QA reviewer loop (MC-4290+4291) still works without Tessa.
## What NOT to do
- Do not change the QA reviewer (already done in MC-4290)
- Do not change the operator (MC-4293)
- Do not change the inbox (MC-4294)
Activity
done
INTERACTIVE
Luci is working...
Details —
Done
· Medium
· Luci
▼
SState
Done
Closed
PPeople
TTiming / Details▼
api (human)
Mission Control
17d ago
16d ago
Advanced / Operator evidence
RRouting owner
ROperator console
Ticket is done; runtime is closed.ticket_marked_doneprofile claude_opus_1m_medium · cwd /home/lucienne/workspace/mission-control · uptime 16d 18h · last activity 16d 14h agoMC is visibility-only. Hermes Luci launches and gates work outside MC, then mirrors evidence/status here.Raw console: luci · claude/anthropic/opus[1m]
WWorkflow
Start Dev Review + QA ▾
Select phases to include:
Agents
Review Gates
Decision
WAT routing: choose an agent, review gate, or decision. Buttons use the live runtime when one is attached.
BLOCKED until MC-4302 is done. Once the review loop exists, add Tessa as the second stage after QA passes. Do not start until MC-4302 is confirmed working.
luci17d ago
Luci picking up this ticket (background worker).
luci17d ago
Ticket picked up by Luci via MC dispatcher.
MC-4303: Wire Tessa as user tester (second Reviewer stage)
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
luci17d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket picked up by Luci via MC dispatcher.
MC-4303: Wire Tessa as user tester (second Reviewer stage)
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
luci17d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket picked up by Luci via MC dispatcher.
MC-4303: Wire Tessa as user tester (second Reviewer stage)
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
luci17d ago
Ticket runtime send failed while dispatching.
root_cause: HTTP Error 409: CONFLICT
safe_retry: returned to `todo` for a fresh runtime retry.
human_input_required: no
system17d ago
RUNTIME TERMINAL STATE (MC-3482 contract)
status: warning
summary: Ticket runtime send failed; parked for automatic recovery.
root_cause: send failed while injecting into ticket runtime: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message was not sent.
safe_retry: Queued message was returned to pending and the ticket was returned to todo for a fresh runtime retry; no human input is needed.
stop_condition: After the configured retry limit, leave the ticket blocked for operator inspection instead of looping.
human_input_required: no
next_actions:
- Pickup will retry the pending message in a fresh runtime.
- Inspect runtime/send only if the retry fails again.
artifacts:
- ticket:MC-4303
luci17d ago
Luci picking up this ticket (background worker).
Luci17d ago
Blocked. Ticket says "do not start until MC-4302 is confirmed working" but MC-4302/4291/4292 referenced deps don't exist in MC DB. Tessa role already plumbed in mc_pickup.py (MC_WORKER_ROLES includes tessa, queue_larry_work_for_tessa_validation exists per MC-2670 single-session model). Need clarification: (a) which ticket actually builds the QA reviewer loop this depends on, or (b) is this ticket obsolete given existing Tessa wiring + single-session model, or (c) should I close this and re-file once the review-loop ticket lands?
luci17d ago
Luci picking up this ticket (background worker).
luci17d ago
[system]: Ticket moved to Todo: Wire Tessa as user tester (second Reviewer stage)
[system]: Ticket moved to Todo: Wire Tessa as user tester (second Reviewer stage)
Luci17d ago
QUESTION: Same blocker stands. Review-loop dep tickets (MC-4302/4291/4292)
absent. Tessa worker role + single-session validation already wired in
mc_pickup.py (MC_WORKER_ROLES, queue_larry_work_for_tessa_validation per
MC-2670). Awaiting direction before taking action.
{"mc_signal":"QUESTION","ticket":"MC-4303","nonce":"MC_TICKET_TURN:4303:177989
1661779:b4a38186","payload":"Still blocked: dep tickets missing, Tessa already
wired via MC-2670 — awaiting direction"}
api17d ago
Orchestrator routing to lucienne controller (campaign owner). Worker question valid:
- MC-4291 done (backlog clear, not the gate)
- MC-4292 inbox (untriaged)
- MC-4302 blocked (real dependency state)
Tessa wiring already exists in mc_pickup.py per MC-2670 single-session model. Lucienne to clarify: (a) is MC-4303 the wiring on top of MC-4302, or (b) obsolete given existing Tessa plumbing, or (c) close-and-re-file post-4302.
Reassigning lucienne for controller call. needs_input.
luci17d ago
Luci picking up this ticket (background worker).
luci17d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket picked up by Luci via MC dispatcher.
MC-4303: Wire Tessa as user tester (second Reviewer stage)
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
luci17d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket picked up by Luci via MC dispatcher.
MC-4303: Wire Tessa as user tester (second Reviewer stage)
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
system17d ago
RUNTIME TERMINAL STATE (MC-3482 contract)
status: error
summary: Ticket runtime send failed; parked for automatic recovery.
root_cause: send failed while injecting into ticket runtime: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message was not sent.
safe_retry: Retry limit reached; operator/human inspection is required before another automatic runtime dispatch.
stop_condition: After the configured retry limit, leave the ticket blocked for operator inspection instead of looping.
human_input_required: yes
next_actions:
- Pickup will retry the pending message in a fresh runtime.
- Inspect runtime/send only if the retry fails again.
artifacts:
- ticket:MC-4303
luci17d ago
Ticket runtime send failed while dispatching.
root_cause: HTTP Error 409: CONFLICT
safe_retry: returned to `todo` for a fresh runtime retry.
human_input_required: no
luci17d ago
Luci picking up this ticket (background worker).
luci17d ago
Ticket moved to Todo: Wire Tessa as user tester (second Reviewer stage)
luci17d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket moved to Todo: Wire Tessa as user tester (second Reviewer stage)
luci17d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket moved to Todo: Wire Tessa as user tester (second Reviewer stage)
luci17d ago
Ticket runtime send failed while dispatching.
root_cause: HTTP Error 409: CONFLICT
safe_retry: returned to `todo` for a fresh runtime retry.
human_input_required: no
system17d ago
RUNTIME TERMINAL STATE (MC-3482 contract)
status: warning
summary: Ticket runtime send failed; parked for automatic recovery.
root_cause: send failed while injecting into ticket runtime: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message was not sent.
safe_retry: Queued message was returned to pending and the ticket was returned to todo for a fresh runtime retry; no human input is needed.
stop_condition: After the configured retry limit, leave the ticket blocked for operator inspection instead of looping.
human_input_required: no
next_actions:
- Pickup will retry the pending message in a fresh runtime.
- Inspect runtime/send only if the retry fails again.
artifacts:
- ticket:MC-4303
elmar17d ago
Controller note: dependency MC-4302 is now done. MC-4303 is not redundant: implement automatic Tessa validation after the reviewer-retry loop passes. Continue the ticket from the current live runtime; use DONE/REVIEW/QUESTION when complete or blocked.
Luci17d ago
DONE: MC-4303 Tessa user-tester gate wired and pushed on
feat/mc-4303-tessa-gate(commit0133d58,branchedoffMC-4291).
Delivered:
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
- mc_tessa_gate.py — gate_on_pass(tid, verdict) hands UI-touching tickets to
Tessaaftershadowpass;act_on_tessa_output(tid, output)reopensonISSUES
with review_cycles bump (cap 3 → needs_input).
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
-Hookinmc_review_retry.pypassbranch(fail-open).
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
-Newflagtessa_gate→MC_ORCH_TESSA_GATE(defaultOFF+kill-switch).
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
-UIdetection:uitagORdiffmatches.html/.css/.js/.jsx/.tsx/.vue/.svelte
or templates|static|components|pages|views paths.
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
-Tessaavailabilitygate:MC_TESSA_AVAILABLE=0→warningcomment,no
reassign.
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
-mc_tessa_gate.py—gate_on_pass(tid, verdict)handsUI-touchingticketsto
Tessa after shadowpass; acton_tessa_output(id, output) reopeson ISSUES
with review_cyclesbump (cap 3 → needs_in).
- Hook in mc_review_retry.pypass branch (fail-open).
New flag tessa_gate → MC_ORCH_TESSA_GATE (default OFF+kill-switch).
UI detection: ui tag OR diff matches .html/.css/.js/.jsx/.tsx/.vue/.svelte
or templates|statc|components|pages|views paths.
- Tessa availability gate: MC_TESSA_AVAILABLE=0 →warningcomment,no
reasign.
- 15 new testspass;MC-4291+MC-4207regressionsclean(26/26+19/19).
Inert until enabled. Depends on MC-4291 merging to master first.
⏵⏵bypasspermissionson (shift+tabtocycle)144375tokens
{"mc_signal":"DONE","ticket":"MC-4303","nonce":"MC_TICKET_TURN:4303:1779897983
164:32e9993f","payload":"Tessagatewiredonpass+UIverdicts;flag-gated,15
tests pass; branch feat/mc-4303-tessa-gate pushed"}
luci17d ago
Workflow action `review_ready` applied. Work ready for review.
api17d ago
Closed (orchestrator). 0133d58 FF-pushed to mission-control master. mc_tessa_gate.py: gate_on_pass hands UI-touching tickets to Tessa after shadow_review pass; act_on_tessa_output reopens on ISSUES. Completes the second-reviewer-stage gate. Branched off MC-4291 retry-loop, chains correctly.
luci17d ago
POST-MERGE / SHADOW-REVIEW EVIDENCE (2026-05-27 19:45 SAST)
1) Branches/master:
- master now at mission-control 579a529 `fix: repair shadow reviewer runner`.
- Required feature commits are ancestors of master:
- feat/mc-4291-review-retry-loop: 4317650
- feat/mc-4303-tessa-gate: 0133d58
- feat/mc-4304-operator-fix-deadworker-killswitch: 3f383e9 + d6a77a0
- `git status --short --branch`: ## master...origin/master
- MC service restarted and active: luci-dashboard.service active after restart.
2) Shadow reviewer root cause/fix:
- Runner was firing but then erroring every run: `AttributeError: module 'mc_shadow_review' has no attribute 'reconcile_human_decisions'`.
- Secondary issue: direct shell runner did not have ZAI/GLM key in process env; semantic_router now reads the key from ~/.hermes/.env fail-open.
- Fix committed/pushed: mission-control 579a529.
- Tests: 79 passed (`test_mc4207_shadow_review`, `test_semantic_router`, `test_mc4291`, `test_mc4303`, `test_mc4304`).
- Manual runner after fix: `reviewed=0 reconciled=0` with no AttributeError.
3) Forced + E2E proof:
- Forced real-ticket review on MC-4303 wrote shadow_reviews id=4: verdict=fail, would_action=return_for_fixes, reviewer_model=glm-4.7.
- E2E smoke ticket MC-4315: dummy worker commit e255dc06010372a01407e5032ddf829f5c01764c; shadow runner wrote shadow_reviews id=5: verdict=pass, would_action=advance, human_decision=accepted_done.
4) Flags enabled after E2E:
- Workspace scheduler commit da608526 enables:
- ticket-pickup: MC_ORCH_SHADOW_REVIEW=1
- shadow-review-runner: MC_ORCH_SHADOW_REVIEW=1 MC_ORCH_REVIEW_RETRY=1 MC_ORCH_TESSA_GATE=1
- Runtime flag check: shadow_review=True, review_retry=True, tessa_gate=True, killswitch=False.
luci17d ago
Cleanup follow-up: deleted checked-in tests/screenshots/ artifacts and pushed mission-control commit 032182e (`chore: remove checked-in browser screenshots`). .gitignore now blocks tests/screenshots/ and .scratchpad/ so browser/Tessa scratch outputs do not re-enter the repo.
luci-operator17d ago
Luci Operator: promoted this assigned `inbox` ticket to `todo` so pickup can run it.
luci-controller17d ago
[controller triage] MC-4303 is not redundant: Tessa exists manually/inline, but this ticket wires automatic Tessa validation after the MC-4302 reviewer-retry loop passes. MC-4302 is now done, so I cleared the stale needs_input state and released MC-4303 to Luci for implementation.
luci-controller17d ago
[controller recovery] Cleared stale runtime-send failure after dependency release. Re-queueing MC-4303 once more; if runtime pickup fails again this is dispatcher/runtime plumbing, not human input.
luci-controller17d ago
[controller recovery] The MC-4303 runtime pane is live after dispatch, despite the dispatcher returning 409. Normalized ticket/runtime state to in_progress/idle to stop pickup loops; worker can continue from the live pane.