Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
"url": "https://github.com/jjackson"
},
"metadata": {
"version": "0.13.321"
"version": "0.13.322"
},
"plugins": [
{
"name": "ace",
"source": "./",
"version": "0.13.321",
"version": "0.13.322",
"description": "AI Connect Engine — orchestrates the CRISPR-Connect lifecycle from idea through app building, Connect setup, LLO management, and closeout"
}
]
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ace",
"version": "0.13.321",
"version": "0.13.322",
"description": "AI Connect Engine — orchestrates the CRISPR-Connect lifecycle from idea through app building, Connect setup, LLO management, and closeout",
"author": {
"name": "Jonathan Jackson",
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.13.321
0.13.322
19 changes: 19 additions & 0 deletions commands/interview-cohort-create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
description: Launch a single Connect Interviews cohort (per-opportunity automation)
argument-hint: <cohort.yaml>
allowed-tools: [Read, Write, Edit, Bash, AskUserQuestion]
---

# /ace:interview-cohort-create

Per-cohort launch automation for the Connect Interviews program: linked-app copies, lookup-table rows, Connect opportunity + payment unit, per-cohort OCS bot routing.

Reads a single YAML spec mirroring the team's Cohort tracker columns. Implements the per_cohort section of `docs/connect-interviews/checklist-schema.yaml`. Idempotent where possible; manual fallbacks for the deferred atoms (linked-app copy, user-field choice add, conditional alert).

Usage:

```
/ace:interview-cohort-create <path-to-cohort.yaml>
```

See `skills/interview-cohort-create/SKILL.md` for the input format and per-step process.
19 changes: 19 additions & 0 deletions commands/interview-domain-bootstrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
description: One-time bootstrap of a Connect Interviews HQ project-space pair (master + downstream)
argument-hint: <domain.yaml>
allowed-tools: [Read, Write, Edit, Bash, AskUserQuestion]
---

# /ace:interview-domain-bootstrap

Stand up the per-project-space plumbing for the Connect Interviews program: HQ domains, linked-project-spaces relationship, Connections, Data Forwarding, Configurable Form Repeaters, Inbound APIs, lookup tables, plus the OCS Dynamic Router Bot.

Reads a single YAML spec and walks the per_domain section of `docs/connect-interviews/checklist-schema.yaml`. Surfaces atom-gap manual steps for the 4 deferred items (subscription provisioning, UCR expression creation, custom user data field, conditional alerts).

Usage:

```
/ace:interview-domain-bootstrap <path-to-domain.yaml>
```

See `skills/interview-domain-bootstrap/SKILL.md` for the input format, atoms used, and per-step process.
24 changes: 24 additions & 0 deletions commands/interview-opp-verify.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
description: Verify a Connect Interviews opportunity matches the launch checklist
argument-hint: <connect-opp-url> [--opp <id> --org <pm-org> --domain <hq-domain> --bot <ocs-experiment-id>]
allowed-tools: [Read, Write, Edit, Bash, AskUserQuestion]
---

# /ace:interview-opp-verify

Read-only verifier for a configured Connect Interviews opportunity. Walks every rule in `docs/connect-interviews/checklist-schema.yaml` (per_program + per_domain + per_cohort + per_user) and grades each rule pass / fail / unverifiable / out_of_band.

Outputs a human-readable report + machine-readable verdict YAML. Cross-system consistency checks (e.g. OCS custom action target URL == HQ Inbound API URL) included.

Usage:

```
/ace:interview-opp-verify https://connect.dimagi.com/a/<org>/opportunity/<opp_id>/
```

Exit codes:
- 0 — all rules pass or out_of_band
- 1 — at least one fail
- 2 — no fails but some unverifiable (operator should review action items)

See `skills/interview-opp-verify/SKILL.md` for the report format, atoms used, and per-rule processing.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ace",
"version": "0.13.321",
"version": "0.13.322",
"description": "AI Connect Engine - orchestrator for building Connect Opps using AI",
"type": "module",
"scripts": {
Expand Down
222 changes: 222 additions & 0 deletions skills/interview-cohort-create/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
---
name: interview-cohort-create
description: >
Per-cohort launch automation for Connect Interviews. Takes a cohort
YAML spec; produces linked-app copies, lookup-table rows, the Connect
opportunity + payment unit, and per-cohort OCS bot routing. Implements
the per_cohort section of docs/connect-interviews/checklist-schema.yaml.
disable-model-invocation: true
---

# Interview Cohort Create

Launch a single cohort for the Connect Interviews program. Idempotent where possible. Designed to run after `/ace:interview-domain-bootstrap` has plumbed the domain.

## Slash command

```
/ace:interview-cohort-create <cohort.yaml>
```

## Input

Single YAML spec mirroring the Cohort tracker columns (per opp-checklist steps 2.3 + 4.3):

```yaml
# Identity
cohort_id: "08TRS" # e.g. "08TRS", "09TRE", "07T1B"
llo_org_slug: "ai-demo-space" # PM org (V1 is ACE-owned)
hq_downstream_domain: "ace-interviews-test"
hq_master_domain: "ace-interviews-master"

# App references (master-side; cohort gets linked copies)
master_learn_app_id: "<couch id>"
master_deliver_app_id: "<couch id>"

# Connect opp
connect_program_id: "<uuid from interview-domain-bootstrap>"
connect_pm_org: "ai-demo-space"
opp_short_description: "Connect Interviews : 08TRS"
opp_long_description: "..." # Free text; checklist step 3.6

# Schedule
schedule:
- { previous: "", next: "te001", frequency_days: 2 }
- { previous: "te001", next: "te002", frequency_days: 2 }
- { previous: "te002", next: "te003", frequency_days: 9999 } # last entry's frequency_days=9999

# Payment + budget
payment_amount_ngn: 2.0 # per cohort tracker
max_users: 40 # rounded up per checklist note
start_date: "2026-05-21" # opp.start_date — NOT updatable later
end_date: "2026-06-30"

# OCS-side
ocs_bot_id: 12213 # The per-domain Dynamic Router Bot from bootstrap
```

## Products

- `ACE/<opp-name>/cohort-create.yaml` — what got created (opp_id, payment_unit_id, app ids, etc.)
- `ACE/<opp-name>/manual-steps.md` — list of manual steps (per-cohort conditional alert)

## Process

Walks per_cohort section of `checklist-schema.yaml`.

### Step 1: Linked-app copies

For each of Learn + Deliver, pull a fresh linked copy on the downstream domain.

**Atom gap**: `commcare_linked_app_copy` is documented in checklist-schema.yaml's atom_gaps but not yet built. The DomainLinkRMIView supports this (via the `create_app_copy` method on apps) but the wire shape needs probing.

**V1 manual fallback**: prompt operator to do the linked-app pull via HQ UI at /a/<downstream>/apps/, then enter the new app ids back into the cohort.yaml.

Once atoms ship:
```
commcare_linked_app_copy({
upstream_domain: hq_master_domain,
downstream_domain: hq_downstream_domain,
master_learn_app_id: <id>,
})
# returns new app_id
```

Rename copies to include cohort_id (e.g. "Connect Interviews (Learn) 08TRS"). Atom gap.

Release a build for each:
```
commcare_make_build({domain: hq_downstream_domain, app_id: <new id>})
commcare_release_build({domain: hq_downstream_domain, app_id: <new id>, build_id: <build_id>})
```

### Step 2: Lookup table rows

Append the cohort's schedule:

```
commcare_lookup_table_append_rows({
domain: hq_downstream_domain,
table_id_or_tag: "interview_schedule",
rows: schedule.map(s => ({
cohort_id: cohort_id,
previous_interview: s.previous,
next_interview: s.next,
frequency_days: String(s.frequency_days),
})),
})
```

### Step 3: User-field choice (cohort_id)

**Manual step (prompt operator):**
> "Visit /a/<downstream>/users/commcare/user_data/ and add '<cohort_id>' as a choice for the cohort_id user field. (Atom not yet built.)"

### Step 4: Connect opportunity

```
connect_create_opportunity({
organization_slug: connect_pm_org,
program_id: connect_program_id,
name: cohort_id, # checklist step 3.2: just the cohort_id
short_description: opp_short_description,
long_description: opp_long_description,
country: "Nigeria",
currency: "NGN",
learn_app: { domain: hq_downstream_domain, cc_app_id: <learn-new-id>, passing_score: 4 },
deliver_app: { domain: hq_downstream_domain, cc_app_id: <deliver-new-id> },
hq_server: "https://www.commcarehq.org/",
api_key: <ACE_HQ_API_KEY>,
start_date: start_date, # cannot be updated later
end_date: end_date,
max_users: max_users,
})
```

Capture the new opp_id.

### Step 5: Payment unit

```
connect_create_payment_unit({
organization_slug: connect_pm_org,
opportunity_id: <opp_id>,
name: `${cohort_id} interview completed successfully`,
amount: payment_amount_ngn,
max_total: schedule.length, # one payment per interview in the schedule
max_daily: 1, # checklist step 4.3
})
```

### Step 6: Opp verification flags

```
connect_set_verification_flags({
organization_slug: connect_pm_org,
opportunity_id: <opp_id>,
flags: { gps: false }, # checklist step 6: GPS off
})
```

### Step 7: Delivery type + active

```
connect_update_opportunity({
organization_slug: connect_pm_org,
opportunity_id: <opp_id>,
delivery_type: "interview",
is_test: false,
})

connect_activate_opportunity({
organization_slug: connect_pm_org,
opportunity_id: <opp_id>,
})
```

### Step 8: Conditional alert

**Manual step (prompt operator):**
> "Visit /a/<downstream>/messaging/conditional/add/ and create a Conditional Alert:
> - Name: '<cohort_id> Payment Conditional Alert'
> - Case type: commcare-user
> - Filter: cohort_id = '<cohort_id>' AND session_completion = 'session completed'
> - Action: submit Connect Survey form with delivery unit configured for payment trigger
> (Atom not yet built — 3-form combined POST.)"

### Step 9: OCS interview-node routing

Per cohort, the Dynamic Router Bot's StaticRouterNode `keywords` need to include this cohort's interview_ids. Modify the existing node's params:

```
# Get current pipeline
pipeline = ocs_get_chatbot_pipeline_id({experiment_id: ocs_bot_id})
# (read the router node's current keywords, add this cohort's interview_ids, save)
```

**Atom gap for V1**: `ocs_update_pipeline_node` not built — only `ocs_add_pipeline_node`. For V1, the StaticRouterNode template already has `keywords: ["default"]`; cohort-specific routing is documented as manual until the update atom ships.

## Idempotency

Steps that detect existing state (opp by name, payment unit by name, lookup row by exact match) skip re-create. Operator can re-run the skill if a single step failed.

## MCP Tools Used

- `commcare_lookup_table_append_rows`, `commcare_release_build`
- `connect_create_opportunity`, `connect_create_payment_unit`, `connect_set_verification_flags`,
`connect_update_opportunity`, `connect_activate_opportunity`, `connect_list_delivery_types`
- `ocs_get_chatbot_pipeline_id`

## Manual fallbacks

V1 manual steps surface in `manual-steps.md`:
- Linked-app copy + rename (atom gap)
- cohort_id user-field choice add (atom gap — hidden-JSON form)
- Conditional alert create (atom gap — 3-form combined POST)
- OCS router-node keywords update (atom gap)

## Change Log

| Date | Change | Author |
|------|--------|--------|
| 2026-05-21 | Initial V1 — atom matrix complete except 4 deferred items | ACE team |
Loading
Loading