# HANDOFF — Expose all Amcom RPCs in CLI + Companion

**Paused:** 2026-07-10 (Tasks 0–20 done) · **spok-api branch:** `claude/open-rcps-docs-fkxcmb` (PR #1) · **HEAD:** `1068f10`

## What this project is
Surface every wrapped Amcom RPC (130 missing from the CLI, 123 from the companion; DataFeed excluded) as CLI subcommands + companion HTTP routes, each lab-verified, then release the chain (npm publish `spok-api` v1.2.0 + companion dep bump). Being executed with **superpowers:subagent-driven-development** (fresh implementer subagent per task → task reviewer → fix loop → ledger).

- **Spec:** `docs/superpowers/specs/2026-07-08-expose-all-rpcs-cli-companion-design.md`
- **Plan (source of truth for tasks + templates T1–T6):** `docs/superpowers/plans/2026-07-08-expose-all-rpcs-cli-companion.md`
- **Progress ledger (authoritative, gitignored):** `.superpowers/sdd/progress.md` — trust this + `git log` after any resume.

## Done so far — spok-api CLI COMPLETE (Tasks 0–20, all reviewed except Task 20 folded into final review)
- **Phase 0** Task 0 — integration harness (`test/integration/helpers.js`: `lab()`, `itLab`, `CreatedRegistry`, `extractSeq(res, key)` exact-key delete-safety).
- **Phase 1 reads (Tasks 1–10)** — ~73 `get` subcommands, all ✅ reviewed. Live: 54 pass / 20 documented skips.
- **Phase 2 writes (Tasks 11–18)** — all 8 categories, ✅ reviewed, **SAFETY SAFE** (create→verify→delete-own on throwaway `ZZ-APITEST` records; on-call test has a runtime guard verifying its chosen group mid is unused first).
- **Phase 3 (Task 19)** — 5 paging cmds wired, `test.skip`, **zero live calls** (structurally impossible to fire).
- **Phase 4 (Task 20)** — reconciled all 175 wrapped RPCs vs XML; rebuilt `dist/`; updated `docs/UNWRAPPED-RPCS.md`. HEAD `1068f10`.

**Full suite (run this way — default concurrency is flaky on the shared lab):**
`SPOK_LAB=1 node --test --test-concurrency=1 test/integration/**/*.test.js` → **69 pass / 30 skip / 0 fail**.

**Wrapper param bugs the lab testing caught + fixed** (all in `src/index.ts`, rebuilt into `dist/`): isPagerByListingId (lid+phnum), isPagerByPhone (phnum), GetEmailAddressByOrder (lid), GetCallerEmailAddress (cid), GetStatusesByFeedId (fid), getIdsAssignments/getIdsAssignmentsXml (+dates), 9 event/notification wrappers (evid/evrseq/stepseq/request_seqnum), deleteAddress (addseq), deleteOncallAssignment/Group/GroupRole, unassignWorkHours (lid), deleteMessageGroup (+reqlid), setListingEnabled (+module), deleteListingDirectoryPhone, assignPagerByLid (pid/dorder), shareListingInstruction (lid), deleteException (mid+exseq), deleteAllPersonalDeviceOptions (lid), unassignContactDevices (lid). Plus completeness: getDirectoriesByUdf (+lid/phtype), getPagingInfo (+lname/fname).

## RESUME HERE — Task 21 (the publish CHECKPOINT — needs user OK)
The spok-api CLI half is done. Remaining work is the release + the companion:

**Task 21 — Release spok-api (⚠️ IRREVERSIBLE — get explicit user go-ahead first):**
1. Push branch; ensure PR #1 CI green.
2. Merge PR #1 to `main` (`gh pr merge 1 --squash`, identity sieteunoseis).
3. On `main`, confirm `package.json` = `1.2.0`; `git tag v1.2.0 && git push origin v1.2.0` → release workflow publishes `spok-api@1.2.0` to npm (npm currently 1.1.2).
4. Confirm `npm view spok-api version` → `1.2.0`.

**Phase 5 — companion (Tasks 22–25), repo `~/development/spok-companion` (on `master` — BRANCH FIRST, identity wordenj/OHSU):**
- Task 22 — add `GET` routes in `src/routes/amcom-read.js` for all Phase-1 read RPCs not already present (grep first), Swagger-tagged. Template T3.
- Task 23 — add write routes in `src/routes/amcom-write.js` for all Phase-2 write RPCs not present, `<Domain> — Write` tags. Template T4. Use the SAME corrected param names proven in the CLI (see bug list above).
- Task 24 — paging routes (`Send*`) with Swagger docs; note no harness fires them (no live send).
- Task 25 — bump `spok-companion/package.json` `spok-api` `^1.0.1`→`^1.2.0`; `npm install`; `npm start`; confirm `/docs` renders all routes.

**Then:** final whole-branch code review (both repos), then superpowers:finishing-a-development-branch.

Companion note: routes call `service.execute(method, params)` directly (see `src/routes/amcom-client.js`), so they work regardless of installed spok-api version — the dep bump is hygiene. amcomapi.xml lives in `spok-companion/docs/amcomapi.xml`.

**Phase 5:** Tasks 22–25 — companion routes (reads, writes, paging) + bump `spok-companion` `spok-api` dep `^1.0.1`→`^1.2.0`. ⚠️ spok-companion is on `master` — **create a feature branch first** (identity: wordenj/OHSU per repo mapping).

## How to build a task brief (controller step)
The plan's bulleted `**Task N**` headers aren't parsed by `scripts/task-brief`, so briefs are composed manually:
```bash
cd /home/netcomm/development/spok-api
PLAN=docs/superpowers/plans/2026-07-08-expose-all-rpcs-cli-companion.md
{ cat .superpowers/sdd/cli-brief-header.md; echo; echo "## YOUR TASK (Phase 1 — CLI reads)"; echo;
  sed -n '/^## Phase 1 — CLI reads/,/^- \[ \] \*\*Task 1 /p' "$PLAN" | sed '/^## Phase 1 — CLI reads/d; /^- \[ \] \*\*Task 1 /d';
  echo; echo "### Task N"; grep -F '**Task N —' "$PLAN"; } > .superpowers/sdd/task-N-brief.md
```
`.superpowers/sdd/cli-brief-header.md` already holds the Global Constraints + Templates T1–T6. For writes, swap the Phase-2 preamble in.

## Non-negotiable constraints
- **Lab only:** `smstetstdb8.ohsu.edu:9722` is the ONLY configured server (active `lab`, ssl+insecure). No prod config exists.
- **No page sends, ever:** the 5 paging RPCs (`SendMessage`, `SubmitMessage`, `SendGroupPage`, `SendPageWithAlert`, `SendToSmartAlert`) are wired but never live-called; tests `it.skip`.
- **Delete only self-created:** writes capture their returned id via `extractSeq(res, "<exactfield>")`; `null` id ⇒ do NOT delete. Never touch pre-existing lab data.
- **Params from `spok-companion/docs/amcomapi.xml`** verbatim (`<parameter name>`); never guess. When a lab call reveals a wrong param, fix `src/index.ts` + CLI command + test together and `npm run build` (rebuild `dist/`).
- Tests gated by `SPOK_LAB=1`. `npx tsc --noEmit` clean before every commit (pre-existing moduleResolution note allowed).
- Commit trailer: `Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>`.

## Reusable live fixtures (real lab data)
- Listing w/ pager+phone+email: `lid=48218` / `mid=66755` (Zhang, An-Sheng); pager pid `15033290798@sms.smartmessagingsuite.com`.
- Plain listing: `lid=322504` / `mid=54361` (Aaron, Ruby).
- Extra: `mid=16818` (Adair, Melissa D — has multiple pagers). Last names "Aaron"/"Zhang" work with `search_type="BEGINS WITH"`.
- No fixture found in-lab for: directory-level UDF, "is-a-pager" via dirseq/phnum, `IsPagerByPhone` positive, `GetStatusesByFeedId` (fid), `GetStatusesByLatestDate`, alt-phone, caller-email positive — these are documented `it.skip`s / clean-wiring asserts, NOT bugs.

## Notes for the final whole-branch review
- Recurring MINOR: several read tests assert only `!res.error` / `res.data` truthy (no fixture to assert content) — consider tightening.
- `src/index.ts` `getDirectoriesByUdf()` is missing optional `lid`/`phtype` params (XML + CLI support them) — fix during Task 20.
- Pattern observed: the PR's wrappers had multiple wrong param names (5 fixed so far in Tasks 2–5); expect more in the write phases — the live tests are what catch them.
