Weekday 10am Eastern cron exports all Webex Calling locations whose
name starts with "Store" to a legacy-format CSV (+E164,Store XXXX),
diffs against the previous baseline, and posts the file plus a change
summary to a configured Webex space.
- src/webex/storePhones.js: paginated GET /telephony/config/locations
- src/services/storePhoneExport.js: CSV format, filename, diff, message
- src/webex/messages.js: bot-token multipart POST /messages with file
- src/jobs/storePhoneExport.js + cron in src/index.js
- scripts/exportStorePhones.js for manual runs (npm run export-store-phones)
- Persist baseline + archives under data/store-phone-export/ (gitignored)
- Dockerfile: create /app/data for volume mount in prod
- CI: align node-version with Dockerfile (20)
Co-authored-by: Cursor <cursoragent@cursor.com>
- 30-test suite (node --test, no framework) covering the exact functions
that have regressed in previous rounds:
* parseStoreArg / parseStoreNumber / storeEmail (helpers)
* greetingForBrand (brand fallback)
* formatE911Address / formatSuite (google response reducer)
* parseNextLink (RFC-5988 pagination — now exported)
* runStep success / non-critical / critical / no-bot paths
- test/setup.js stubs required env vars so any src/ module can be
imported cleanly; loaded via --import once per test process
- npm run test wired up; directory form works on Node 20 + 22
- .gitea/workflows/ci.yml runs lint + format:check + test on push/PR
to main, on Node 22 to match the runtime image
- Exclude test/ and .gitea/ from the Docker build context
- Exclude docker/ from bot Prettier scope (remote-agent is its own
sub-project with its own tooling)
Co-authored-by: Cursor <cursoragent@cursor.com>