Stage 2 of ACE Phase 7 (Plan B). Consumes the per-persona spec YAMLs
written by synthetic-walkthrough-spec, dispatches the
canopy:walkthrough skill once per persona, and uploads each resulting
HTML slideshow + scored screenshots to the run folder. Each invocation
appends to phases.synthetic-data-and-workflows.products.synthetic.walkthroughs[]
in the current run's run_state.yaml. Each run accumulates its
own walkthroughs list as personas are dispatched within that run; the
list does NOT chain across runs (every /ace:run is independent).
Operators reviewing walkthrough history across multiple runs look at
each run's state file separately or consult ace-web's run listing.
-
Verify the canopy plugin is installed. Run:
ls ~/.claude/plugins/marketplaces/canopy/plugins/canopy/skills/walkthrough/SKILL.md
If missing, halt with: "canopy plugin not installed. Run
/plugin install canopy@dimagi-claude-workflows (or whatever
marketplace ships canopy) and retry."
-
Verify the browse binary is built. The canopy walkthrough skill
requires ~/.claude/skills/gstack/browse/dist/browse (or a project-local
copy). Run:
B=~/.claude/skills/gstack/browse/dist/browse
[ -x "$B" ] && echo READY || echo "NEEDS_SETUP: cd ~/.claude/skills/browse && ./setup"
If NEEDS_SETUP, halt with the bootstrap instruction.
-
Verify ACE_HQ_USERNAME / ACE_HQ_PASSWORD are set. Read
${CLAUDE_PLUGIN_DATA}/.env. If either is unset:
"CommCareHQ creds are not configured. Inject from 1Password via
/ace:setup --force-env (preserves local-only secrets; do NOT raw
op inject -o $CLAUDE_PLUGIN_DATA/.env, which drops them) and retry.
The labs walkthrough login uses these creds to drive the headless
OAuth-via-CCHQ flow."
-
Verify bin/ace-labs-walkthrough-login is reachable. Run:
ls ~/.claude/plugins/cache/ace/ace/$(cat ~/.claude/plugins/marketplaces/ace/VERSION)/bin/ace-labs-walkthrough-login
If missing, the installed plugin cache is stale. Run /ace:update
and retry. (This script reuses mcp/connect/auth/hq-oauth-login.ts
for the Connect side and mcp/connect-labs/auth/labs-oauth-login.ts
for the labs OAuth click-through — same Playwright session lib used
by every other ACE login flow.)
-
Read the spec. Load
7-synthetic/synthetic-walkthrough-spec_<persona>.yaml from Drive
via drive_read_file. If the file is missing, skip the persona with
a [WARN] and continue (don't halt — partial decks are better than
none).
-
Stage the spec locally. canopy:walkthrough reads specs from
docs/walkthroughs/<name>.yaml in the current repo. Write the spec
body to:
./docs/walkthroughs/<spec.name>.yaml
…where <spec.name> is the YAML's name field (e.g.,
turmeric-funder-walkthrough). Create the directory if needed.
This is a transient local artifact — gitignored on a per-repo basis.
Operators running this skill from outside an ace checkout will have
their cwd's docs/walkthroughs/ polluted; document that in the
skill output if it happens.
-
Dispatch canopy:walkthrough. Invoke:
/canopy:walkthrough <spec.name>
The canopy skill handles auth (via the spec's auth.command block —
which calls bin/ace-labs-walkthrough-login, since canopy v0.2.79
walkthroughs targeting labs URLs use ACE's labs-OAuth helper, not
ace-web's /auth/e2e-login/ shared-secret bypass), browser setup,
scene capture, per-scene canopy:visual-judge dispatch (5-dim
Tough Judge scoring per scene), deck generation, and writes:
screenshots/walkthroughs/<spec.name>.html (deck)
screenshots/walkthroughs/<spec.name>.json (sidecar with scores)
/tmp/walkthrough-screenshots/<name>-<timestamp>/scene_*.png
(per-scene PNGs)
Capture the dispatch's exit status. If non-zero (auth failed, browse
crashed, AI judge returned malformed output), surface the failure
verbatim and skip to the next persona.
-
Stage outputs into the run folder.
For each successful run, build:
7-synthetic/walkthroughs/<persona>-<YYYYMMDD-HHMMSS>/
slideshow.html
scenes/
scene_1.png ... scene_N.png
eval.json
Upload via:
drive_create_folder (find-or-create) for the per-persona folder
drive_upload_binary for each .png (mimeType image/png)
drive_create_file for slideshow.html (find-or-update; the
gdrive MCP converts to a Google Doc — this is fine; viewers
download to view as HTML)
drive_create_file for eval.json
On any upload failure, halt this persona's run, leave partial state
in Drive, and continue to the next persona. Surface the failure in
the run summary.
-
Append to
phases.synthetic-data-and-workflows.products.synthetic.walkthroughs[]
in the current run's run_state.yaml via read-modify-write:
-
drive_read_file on the current run's run_state.yaml;
extract the existing products.synthetic block (this run's own
writes only — there's no cross-run chain).
-
Append the new entry to walkthroughs[]; keep sibling sub-keys
(enabled, current_*, workflows, etc.) intact:
synthetic:
walkthroughs:
- persona: <persona>
spec_artifact: <Drive ID of the spec YAML>
slideshow_artifact: <Drive ID>
eval_artifact: <Drive ID>
scene_count: <int>
eval_score: <float — average across scenes>
run_at: <ISO>
-
update_yaml_file with merge: 'deep' on the
phases.synthetic-data-and-workflows.products.synthetic.walkthroughs
payload (deep preserves sibling sub-keys + the phase's
status/steps; two-level would replace the whole phase block,
#572/#587). The walkthroughs list is read-appended-rewritten in
full above, so deep's array-replace is correct.
No write to opp.yaml.synthetic — synthetic state is per-run only.
Within a run, re-runs of this skill (per-persona) APPEND new
entries; never overwrite existing ones. The list grows within
the run's walkthrough history.
-
Update run_state.yaml. Read-merge-write the per-persona step:
phases:
synthetic-data-and-workflows:
steps:
synthetic-walkthrough-run:
status: <done|partial>
personas:
<persona>:
status: done
eval_score: <float>
run_at: <ISO>
artifacts:
slideshow: <Drive ID>
eval: <Drive ID>