fix(phase 6): require Learn smoke + walk-Learn-first Deliver smoke for two-app opps#354
Merged
Merged
Conversation
…r two-app opps
Connect's mobile UI only surfaces the Deliver app after the FLW completes
the Learn-app modules + final assessment AND that assessment-pass syncs
to Connect. There is no UI affordance to jump from claim-opp into Deliver
without walking Learn to completion first ("Once you have completed the
learning assessment, you will transition to delivery"). Phase 6 was
producing recipe-vs-app-state mismatches for multi-stage two-app opps
because Phase 2 emitted 0 Learn journeys, Phase 3 wrote `learn: 0`
smoke counts, and Phase 6 ran the Deliver smoke anyway — which physically
cannot reach Deliver from the claim handoff.
Three-skill structural fix + supporting palette + learning doc:
- skills/pdd-to-app-journeys: new coverage rule 4 — every PDD with a
Learn app MUST emit `training-completion-smoke` (app: learn,
is_smoke: true). Deeper Learn journeys move to /ace:qa-deep.
- skills/app-test-cases: Step 2 codifies the two-app coverage invariant
(learn=1 AND deliver=1, halt at Phase 2 otherwise) + documents the
faithful Deliver-smoke composition (walk all Learn modules to
completion → sync → tap Resume → certificate → Download Delivery
gate → Deliver mode). Step 5 enforces the invariant pre-write.
Step 3's entry-point template references the new deliver-launch
palette and updates the Learn-vs-Deliver guidance.
- skills/app-screenshot-capture: Step 2's pre-flight table was already
correct (halt on `learn count != 1 OR deliver count != 1`), but agent
discipline drifted past it. Strengthened the commentary with the
malaria-itn-app incident and an explicit "don't rationalize past
this" anti-pattern callout.
- mcp/mobile/recipes/static/deliver-launch.yaml: new static palette
driving atlas §§ 8/9/10 transitions (certificate → Download Delivery
gate → Deliver mode StandardHomeActivity). Anchors on text labels at
§§ 8/9 (resource-IDs TBD) + structural `viewJobCard` at § 10
(verified per atlas).
- docs/learnings/2026-05-18-connect-gates-deliver-on-learn-completion.md:
captures the invariant + cross-references the atlas + outstanding
resource-ID dump work.
Surfaced on malaria-itn-app run 20260517-1829 Phase 6 verdict
(structural_progress_fraction 0.83, 9 valid Learn-app screenshots,
recipe halt at `tapOn "V1 Long Visit"` because the device was sitting
on Learn's `actionBar="Malaria ITN SBC Training (Learn)"` — the
Deliver V1 form was never reachable from that surface).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jjackson
added a commit
that referenced
this pull request
May 19, 2026
…step ordering Two orthogonal bugs surfaced on malaria-itn-fgd/20260515-1645 Phase 6 attempt 12. Both unrelated to PR #354's Learn-Deliver chain scope. Bug A — learn-tap-module.yaml Branch-B over-fires when form-name != module-name: The same-name-suppressed-auto-skip branch guarded only on `screen_suite_menu_list visible AND nav_btn_next NOT visible`, then re-tapped `text:${MODULE_NAME}`. On J1 (module "Briefing Acknowledgement" → form "Acknowledge Readiness"), the form-list screen's toolbar still reads ${MODULE_NAME}, so Branch-B fired and re-tapped the non-tappable toolbar TextView instead of the form row. Fix: nested runFlow with inner guard `visible: text: ${MODULE_NAME}, below: id: screen_suite_menu_list` so the text-match is scoped to the list body. When form-name != module-name no body row matches, Branch-B skips, caller's next learn-tap-module(FORM_NAME) drills the form row by its own label. Bug B — sweepStaleEmulatorState ordering (PR #349 follow-up): PR #349 wired up the orphan-qemu sweep and adb-server restart but (a) used a conservative `qemuPids.length >= liveCount + 2` kill threshold that left the attempt-12 signature (2 orphan qemu + 1 stale adb-devices entry, 2 NOT >= 1+2) below the kill bar, and (b) ran the adb-restart immediately after the kill without waiting for the kernel to release the emulator-NNNN TCP sockets — letting the freshly-restarted daemon adopt the wedged-port state. Result: 2 of the next 3 ensureAvdRunning calls still failed with "package service did not bind" until a second manual adb kill-server/start-server fired inside the dispatch. Fix: 1. Loosen the orphan kill to fire whenever qemuPids.length > liveCount. 2. Add a 500ms socket-release wait between the last orphan SIGKILL and adb kill-server. Tests: - static-recipe-invariants.test.ts asserts Branch-B's inner runFlow has `visible: text: ${MODULE_NAME}, below: id: screen_suite_menu_list`. - avd.test.ts asserts orphan-qemu kill precedes adb kill-server AND there's a ≥400ms gap between them (we wait 500ms, 100ms scheduling slack). Second test asserts the loosened threshold actually fires kills on the attempt-12 2-PID + 1-live-device signature. Live reproducer: /Users/jjackson/.maestro/tests/2026-05-19_151650/ screenshot-❌-1779218294468-(chunk-0.yaml).png. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2 tasks
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
Phase 6 multi-stage two-app opps produce recipe-vs-app-state mismatches because Connect's UI gates the Deliver app behind Learn-assessment completion, but Phase 2 was emitting 0 Learn journeys and Phase 3 was writing `smoke_journeys_per_app: {learn: 0, deliver: 1}` and Phase 6 ran the Deliver smoke anyway — which physically cannot reach Deliver from the post-claim handoff.
Three-skill structural fix + new static palette + learning doc.
Evidence
malaria-itn-app run `20260517-1829` Phase 6 verdict:
Connect's opp-detail screen makes the contract explicit: "Once you have completed the learning assessment, you will transition to delivery."
Changes
Outstanding
Test plan
🤖 Generated with Claude Code