一键导入
ocs-chatbot-qa
Exercise the per-opp OCS chatbot via its anonymous widget and capture a transcript with structural checks. Modes: --quick / --deep / --monitor.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Exercise the per-opp OCS chatbot via its anonymous widget and capture a transcript with structural checks. Modes: --quick / --deep / --monitor.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Produce a domain-expert-facing before/after (pre-post) Google Doc for a DDD narrative iteration, and read the expert's edits back. Pull the verbatim CURRENT narration from canopy-web, apply reviewer feedback into a PROPOSED next version, publish a scannable side-by-side doc a non-engineer can review, then read their suggestion-mode edits via the structured Doc. Use when iterating a Connect DDD narrative on expert feedback (e.g. RF Surveys / Sophie), when asked to "make a before/after of the narration", "iterate the narrative on <expert>'s feedback", or "let <expert> sign off on the language".
Apply the two HQ-layer standing-instruction settings Nova can't set at build time — camera-only photo capture (appearance="acquire" on Deliver image uploads) and grid menu display on every module — to the deployed draft apps, then resolve the matching Phase-3 residuals. Runs between app-deploy and app-release.
Build the CommCare Learn (training) app from the PDD via Nova's /nova:autobuild. Captures nova_app_id and writes a structure summary.
Render a training deck spec.yaml into a Google Slides deck via the 14-stencil ACE template. Produces a presentable Slides URL.
Phase 3 § Step 2.8 — structural + install-time QA on the released Learn + Deliver CCZs. Downloads each CCZ via commcare_download_ccz, parses the zip + suite.xml + form XMLs, verifies form counts + Connect-marker presence match the Nova blueprint, then runs commcare-cli `validate` + `play` as install-time runtime gates. AVD-free, Connect-free — purely CCHQ-side. Halts loud on mismatch.
Run app smoke recipes against a local AVD and capture per-step screenshots for the training deck. Per-opp content only.
| name | ocs-chatbot-qa |
| description | Exercise the per-opp OCS chatbot via its anonymous widget and capture a transcript with structural checks. Modes: --quick / --deep / --monitor. |
| disable-model-invocation | true |
Talk to a deployed ACE OCS chatbot and capture what it says into a
structured transcript at
runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-<mode>.md. This skill is
the qa half of
the qa/eval pair — it captures evidence and runs cheap structural checks.
The LLM-as-Judge grading happens separately in ocs-chatbot-eval.
| Source | Artifact | Used for |
|---|---|---|
| Phase 5 | 5-ocs/ocs-agent-setup.md | experiment_id, widget URL, embed credentials |
Phase 1 (--deep only) | 2-scenarios/pdd-to-test-prompts.md | opp-specific prompt suite + expected-answer summaries |
5-ocs/ocs-chatbot-qa_transcript-<mode>.md — chat transcript with structural checks (response received, no errors, citations present)Called from the ocs-setup agent in Phase 5 (--quick only — shallow
3-prompt smoke), from the /ace:qa-deep slash command (--deep,
manual pre-launch), and from execution-manager in Phase 9
(--monitor). Each call is paired with an immediately following
ocs-chatbot-eval call in the same mode.
See skills/README.md § QA vs Eval — the two-phase pattern for the
rationale and artifact-path contract.
| Mode | Suite size | When it runs | Capture written to |
|---|---|---|---|
--quick | 3 smoke questions | Phase 5 Step 2 (post-setup) | runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-quick.md |
--deep | Full suite + opp-specific prompts from test-prompts.md | /ace:qa-deep (manual, pre-launch) | runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-deep.md |
--monitor | Full suite, scheduled | Phase 6 recurring, ad-hoc | runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-monitor.md |
If no mode is passed, default to --quick.
This skill is synchronous and time-boxed. Phase 5's deep capture
once spun for 3+ hours waiting on a fictional "background task" — that
pattern is banned (see agents/ace-orchestrator.md § Long-Running Skills — No Fake Background Tasks). Concrete budget:
status: complete in 90s, abort that prompt, write
structural_pass: false with structural_notes: "timeout @ 90s",
and continue to the next prompt.min(90s × N_prompts, 30 min). Track
elapsed with date +%s checkpoints around the chat loop. If the cap
is reached mid-suite, stop sending new prompts, write the transcript
with complete: false + prompts_captured: <N> / prompts_remaining: <M>, return. For --quick the cap is 270s for the 3-prompt universal
suite, scaling to 360s / 450s when focus-group archetype appends
1–2 archetype-specific prompts (see Step 4 --quick suite below).[BLOCKER] auto_surfaced entry
for the eval skill.ScheduleWakeup from inside this skill. Phase 5 is
foreground sequential work; deferring the agent doesn't background
the chat loop. If you can't finish in budget, fail loud and write
the partial — the orchestrator decides whether to re-dispatch.Resolve the target bot's embed credentials:
experiment_id is provided, call ocs_get_chatbot_embed_info to
get public_id + embed_keyopp_name is provided, read
ACE/<opp-name>/runs/<run-id>/5-ocs/ocs-agent-setup.md$OCS_GOLDEN_TEMPLATE_ID from the envembed_key and public_id are needed for the anonymous chat APIEnv-source note. ACE env vars (OCS_GOLDEN_TEMPLATE_ID,
OCS_TEAM_SLUG, OCS_SHARED_COLLECTION_ID,
OCS_LLM_PROVIDER_ID, OCS_EMBEDDING_MODEL_ID) live at
$CLAUDE_PLUGIN_DATA/.env, not the shell env. When running this
skill programmatically (subagent dispatch, scripts) the env file
must be sourced first. The ACE plugin's env-loading layer handles
this for interactive /ace:* slash commands; manual invocations
need an explicit source $CLAUDE_PLUGIN_DATA/.env (or equivalent).
Liveness probe before the suite (mandatory). Before sending
any suite prompt, send a single 1-token smoke probe via
ocs_send_test_message(public_id, embed_key, "ping") and time it.
auto_surfaced: WARN "OCS ping responded in <Ns>; suite may run slow" for the eval. Don't
halt — the suite cap will catch a true stall./ace:ocs-login), OCS rate limit, dead chatbot
(is_archived: true). Surface the cause in the error message.The probe takes ~2s when healthy. It's the cheapest pre-flight that distinguishes "OCS is responsive" from "absence of output" — which was the single biggest observability gap in the 0.11.5-era Phase 5 capture loop.
Resume from partial capture — --deep / --monitor only.
Check for an existing transcript at the destination path
(ACE/<opp-name>/runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-<mode>.md,
or 9-execution-manager/... for --monitor).
complete: true in the header: the suite
already ran cleanly. Skip the chat loop entirely; the caller can
re-dispatch the eval against the existing transcript.complete: false: parse the entries already
captured. Build the remaining-prompts list as <full suite> - <captured-prompt-strings>. The chat loop in Step 5 picks up at
the next uncaptured prompt; the file is appended-to in place.--quick skips this step entirely. The 270s wall-clock cap is
small enough that resume-from-partial doesn't pay for itself —
re-running burns at most one cap-bound suite. Step 5's --quick
write strategy is single-shot at suite end, so there is no partial
transcript to resume from.
Build the test prompt suite by mode:
--quick suite (3 universal + 0–2 archetype-specific)The 3 universal Connect-domain questions apply to any opportunity
and primarily exercise the shared collection. Cheap shallow
gate (~3 LLM judge calls, single dimension) for the Phase 5→6
hand-off; deep multi-dimensional grading lives in /ace:qa-deep.
Universal 3 (always run):
Archetype-specific extras (append for focus-group only):
For focus-group opps where the OCS chatbot is the primary
facilitator surface (see ocs-agent-setup/SKILL.md § Process step 7),
the 3 universal prompts above primarily exercise shared-collection
retrieval and would pass even if the opp-specific collection was
mis-loaded. Append 1–2 archetype-derived prompts drawn from
2-scenarios/pdd-to-test-prompts.md to get shallow signal on
opp-specific RAG. Pick categories that exercise the gdoc-vs-form
distinction:
gdoc-writing-guidance — e.g. "What should I put in
section 3 of my gdoc?"facilitation-technique — e.g. "How do I probe Q9
without leading?"Bump the wall-clock cap from 270s to 360s for focus-group
(3 universal + 1 archetype = 4 prompts × 90s) or 450s (3+2 = 5).
For atomic-visit and multi-stage, the 3 universal prompts are
sufficient — the Learn app carries the bulk of opp-specific training
content, not the chatbot, so opp-specific RAG signal is less
load-bearing at the shallow gate. The 270s cap stays.
--deep suite (full — pre-launch)Connect-general prompts (shared collection):
ACE-specific prompts (golden template prompt):
Opp-specific prompts (only if opp_name is provided):
ACE/<opp-name>/runs/<run-id>/2-scenarios/pdd-to-test-prompts.md — produced in Phase 1 by
the pdd-to-test-prompts skill. Each entry has a question + an
expected-answer summary that ocs-chatbot-eval uses as ground truthEdge-case extras:
--monitor suite--deep but skips the edge-case extras (they're stable).Chat with the bot — time-boxed, write strategy branches on mode:
POST /api/chat/start/
with X-Embed-Key header and the Referer set to the allowed origin.SUITE_START = $(date +%s)).Write strategy:
--quick — buffer in memory, single write at suite end. 3
prompts × 90s = 270s hard cap; the suite either finishes or is
deterministically aborted in a small window. Per-prompt CAS writes
would cost N+1 Drive RTTs (~5 calls for 3 prompts including the
metadata flush) for recovery value that's negligible against a
270s cap. Build entries in memory; Step 7 does one
drive_create_file for the entire transcript.--deep / --monitor — incremental writes with CAS. Suites
run 15–30 minutes; resume-from-partial after a kill is real
value. Each entry gets appended via drive_update_file with
ifMatchRevisionId (revisionVersion CAS, added 0.11.3) so the
transcript file is durable mid-loop.For each prompt (skipping any already in the partial transcript
from Step 3 — --deep/--monitor only; --quick always starts
fresh because nothing is persisted mid-loop):
PROMPT_START = $(date +%s)).POST /api/chat/{session_id}/message/.GET /api/chat/{session_id}/{task_id}/poll/ until
status: "complete" OR per-prompt timeout (90s) elapses.
On timeout: capture an empty response, set
structural_pass: false, structural_notes: "timeout @ 90s".--quick: append to in-memory buffer.--deep / --monitor: drive_update_file with
ifMatchRevisionId from the prior read. The transcript was
created on first prompt with the complete: false header;
each subsequent entry is appended in place. Update the
header's prompts_captured counter on every write.($(date +%s) - SUITE_START) > min(90 × N_prompts, 1800) —
stop the loop. Don't send another prompt. Continue to Step 7.structural_pass: false (timeout or error), stop the loop.
OCS is unhealthy; burning the rest of the budget produces
noise. Before reporting WHY, run the trace triage below —
do NOT write "platform outage" into the blocker text on the
strength of the generic fallback alone.ocs_send_test_message throws OCS generation error, the atom
appends [session <id>; underlying trace: <url> …] (fetched
from /api/sessions/<id>/ → messages[].metadata.trace_info).
Open that trace URL (team login / Playwright cookies) — it
carries the REAL error OCS hides behind the "intermittent
error related to load" fallback (task_utils.py, debug_mode
off). Record the underlying error verbatim in
structural_notes and the blocker text. Known class:
401 authentication_error: invalid x-api-key = the TEAM's LLM
provider key is dead — every bot including the pristine golden
template fails identically, so "golden fails too" proves
key-scope, NOT platform-scope (jjackson/ace#743; the
2026-06-09 incident lost a session to that misread). Repair:
re-key the provider at
/a/<team>/service_providers/llm/<pk>/ (key source of truth:
1P ACE - Anthropic API Key (OCS connect-ace)), then re-run
this skill — no chatbot config change needed.--quick, metadata flush for --deep/--monitor).Run structural checks on each response (cheap, deterministic — these are qa-side checks, not LLM judgment):
response_received: non-empty string within timeoutno_error: no error marker in the response (e.g., not a "sorry,
something went wrong" fallback). On the generic fallback, include
the atom's [session …; underlying trace: …] pointer in
structural_notes (see Step 5.9 — the fallback text itself never
names the real failure)has_citations: for prompts where the expected answer is KB-sourced,
cited_files is non-emptystructural_pass: true | false and a structural_notes
string for the judge (and humans) to readFinal transcript write (mode-dependent):
--quick: single create. Build the full transcript in memory
from the in-memory buffer + completed metadata, then call
drive_create_file once with the assembled content. One Drive
RTT.--deep / --monitor: metadata-only flush. Entries were
written incrementally during Step 5 — drive_update_file here
just updates the header.In both cases, the closing metadata is:
complete: true | false (true on clean loop exit; false on
wall-clock cap hit or circuit-break)prompts_captured: <N> and prompts_remaining: <M> if partialstructural_pass_rate: <X/N>suite_elapsed_seconds: <total wall clock>Path: ACE/<opp-name>/runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-<mode>.md.
If no opp_name is provided (golden-template-no-opp runs), there is
no run-id available, so fall back to the legacy dated form:
ACE/golden-template/qa-captures/YYYY-MM-DD-ocs-chat-<mode>.md.
This is the only surviving use of the dated qa-captures/ form;
per-opp runs always use the run-scoped path above. ocs-chatbot-eval
reads whichever path the producer wrote to. For --quick runs
against the golden template with no opp, stdout summary is still
emitted, but a transcript file is also written so --deep and
--monitor runs have something to re-grade later. Shape:
# OCS Chatbot QA Capture
Date: YYYY-MM-DD
Target: <experiment_id> (<bot name>)
Mode: quick | deep | monitor
Capture method: widget # widget | openai-compat
Suite size: N prompts
Prompts captured: N # may be < suite size if budget hit
Prompts remaining: 0 # >0 means partial; eval handles partials
Complete: true # false = budget hit or circuit-break
Suite elapsed: 142s
Structural pass rate: <X/N>
## Entries
### Entry 1
- **Category:** connect-general
- **Prompt:** How do I review and approve flagged deliveries?
- **Expected answer summary:** <from suite or test-prompts.md>
- **Expected tags:** []
- **Expected escalation:** none
- **Response content:**
<the bot's reply, verbatim>
- **Cited files:** [doc-42, doc-17]
- **Tags:** []
- **Elapsed:** 4.3s
- **Structural pass:** true
- **Structural notes:** —
### Entry 2
...
The transcript is the machine-readable + human-readable input to
ocs-chatbot-eval. Keep every entry's expected_* fields populated so
the judge can grade without re-deriving. Partial transcripts
(Complete: false) are still graded — eval reports them as
incomplete-coverage rather than failing.
Return structural summary:
total_prompts, prompts_captured, structural_pass_count,
structural_fail_count, capture_path, complete: true | false,
suite_elapsed_seconds--quick, also print to stdout so the agent can see it without
reading the capture fileStructural gate (mode-dependent):
--quick: structural fail rate > 0 → escalate (the bot is miswired,
not a judgment call). Eval is skipped.--deep / --monitor: never block at the qa layer. Even a partially
broken response is worth judging; eval distinguishes noise from
regression. Report structural fails as [INFO] in the eval's gate
brief inputs.ocs_get_chatbot_embed_info (Step 1 — resolve experiment_id
→ embed credentials).ocs_send_test_message (Step 2 ONLY — single 1-token liveness
probe before the suite). Do not use ocs_send_test_message for the
suite itself — it strips cited_files, tags, session_id, and
elapsed_ms from its return shape, which makes the transcript
structurally ungradable for the citation and tagging dimensions of
ocs-chatbot-eval. The suite uses raw widget HTTP.
StaleOcsSubprocessError (a 403
session_token_required even though /api/chat/start/ issued a
per-session token), the running ace-ocs MCP subprocess predates the
#742 token-threading fix — /reload-plugins does NOT respawn it; a
full Claude Code restart does. The Step 5 raw-widget-HTTP path threads
X-Session-Token itself, so it is a faithful fallback for the quick
gate: capture the quick suite out-of-band via Step 5's HTTP handshake
and proceed rather than blocking the run; recommend a Claude restart
before the next session to restore the native atom. (If a restart does
NOT clear it, the OCS session-token contract drifted again — re-open
#742.)POST /api/chat/start/
→ POST /api/chat/{session_id}/message/ → GET /api/chat/{session_id}/{task_id}/poll/. This path returns the full
transcript schema.drive_create_file — Step 7 single transcript write on --quick;
Step 5 first-write on --deep/--monitor.drive_update_file with ifMatchRevisionId — Step 5 incremental
appends and Step 7 metadata flush on --deep/--monitor only.
Not used on --quick.drive_read_file — Step 3 resume-from-partial on
--deep/--monitor only.ocs-setup or execution-manager) dispatches
ocs-chatbot-eval next.When --dry-run is active:
| Date | Change | Author |
|---|---|---|
| 2026-05-05 | Path-scheme migration. Transcripts now write to runs/<run-id>/5-ocs/ocs-chatbot-qa_transcript-<mode>.md (or 9-execution-manager/... for --monitor), per the manifest. The opp-level qa-captures/ directory is retired; the only surviving use of the dated qa-captures/ form is the golden-template no-opp fallback (ACE/golden-template/qa-captures/<dated>.md). Resume-from-partial check (Step 3) re-pointed at the new path. No behavior change beyond paths. | ACE team |
| 2026-05-05 | --quick switched to single-shot write. Buffer entries in memory and call drive_create_file once at suite end (Step 7). Reduces Drive RTTs on --quick from N+1 (read+write per prompt + metadata) to 1. The incremental CAS-write strategy still applies on --deep/--monitor where 15–30 min suite runtimes make resume-from-partial worth the cost. Step 3 resume-from-partial is a --deep/--monitor-only step now (--quick's 270s cap is short enough that re-running is cheaper than the resume bookkeeping). | ACE team |
| 2026-05-15 | Extend --quick suite with archetype-specific prompts for focus-group (1–2 from pdd-to-test-prompts.md gdoc-writing-guidance + facilitation-technique categories) since the 3 universal Connect-domain prompts primarily exercise shared-collection retrieval and would pass even if the opp-specific collection was mis-loaded. Wall-clock cap scales to 360s/450s for focus-group. Atomic-visit / multi-stage stay at the 3-prompt / 270s baseline. Prompted by malaria-itn-fgd/20260514-2352 Phase 5 observation. | ACE team |
| 2026-06-09 | Trace triage on generation errors (Step 5.9). On circuit-break / all-fail, the skill must open the session trace URL the atom now appends to OCS generation error failures and record the underlying provider error verbatim — never diagnose "platform outage" from the generic "intermittent load" fallback. Root incident: bednet-spot-check/20260609-0909 lost a session to a revoked team Anthropic key (401 invalid x-api-key) misread as a team-wide OCS outage because the golden-template control sat behind the same dead key (jjackson/ace#743). Atom-side enrichment: mcp/ocs/backends/rest.ts::describeSessionTrace. | ACE team |