|
| 1 | +# CLAUDE.md — Message Segment Calculator |
| 2 | + |
| 3 | +You are a coding assistant working on Twilio's Message Segment Calculator, a TypeScript library and browser tool that helps customers understand how SMS and RCS messages are segmented and encoded. |
| 4 | + |
| 5 | +## Quick Reference |
| 6 | + |
| 7 | +```bash |
| 8 | +npm install # Install dependencies |
| 9 | +npm test # Type-check (tsc) + run tests (jest) |
| 10 | +npm run lint # ESLint on src/**/*.ts |
| 11 | +npm run lint:fix # ESLint with auto-fix |
| 12 | +npm run check # Lint + test (mirrors CI) |
| 13 | +npm run release # Type-check + webpack build (outputs to docs/scripts/) |
| 14 | +npm run build # Type-check only (tsc) |
| 15 | +npm run test:e2e # Playwright e2e tests (serves docs/ locally) |
| 16 | +npm run test:e2e:ui # Playwright interactive UI mode |
| 17 | +``` |
| 18 | + |
| 19 | +## Project Structure |
| 20 | + |
| 21 | +``` |
| 22 | +src/ |
| 23 | + libs/ # Core library (encoding, segmentation) |
| 24 | + SegmentedMessage.ts # SMS segmentation logic (GSM-7 / UCS-2) |
| 25 | + RcsSegmentedMessage.ts # RCS segmentation logic (UTF-8) |
| 26 | + EncodedChar.ts # Single character with encoding info (isGSM7, codeUnits) |
| 27 | + Segment.ts # Segment container (extends Array) |
| 28 | + UserDataHeader.ts # UDH for multi-segment messages |
| 29 | + UnicodeToGSM.ts # GSM-7 character mapping table |
| 30 | + SmartEncodingMap.ts # Twilio Smart Encoding replacements |
| 31 | + textUtils.ts # Grapheme splitting utilities |
| 32 | + browser/ # Browser UI modules |
| 33 | + main.ts # Entry point, DOM wiring, event listeners |
| 34 | + segmenter.ts # Analysis functions (analyzeSms, analyzeRcs) |
| 35 | + renderer.ts # DOM rendering (segment tape, char detail, stats) |
| 36 | + types.ts # Shared type definitions (SmsAnalysis, RcsAnalysis, etc.) |
| 37 | + global.ts # Library exports for global scope |
| 38 | + index.ts # NPM package entry point |
| 39 | +docs/ # GitHub Pages site |
| 40 | + index.html # Main page |
| 41 | + scripts/ # Built JS bundles (from webpack) |
| 42 | + styles/ # CSS (tokens.css, layout.css, components.css, animations.css) |
| 43 | + pr-reviews/ # 3-agent + 1-human PR review docs |
| 44 | +tests/ # Test suites |
| 45 | + *.test.js # Jest unit tests |
| 46 | + e2e/ # Playwright e2e tests (char-detail.spec.ts, etc.) |
| 47 | +dist/ # Built library output (tsc) |
| 48 | +``` |
| 49 | + |
| 50 | +## Key Architecture Concepts |
| 51 | + |
| 52 | +### SMS Encoding |
| 53 | + |
| 54 | +- **GSM-7**: 7-bit encoding, 160 chars/segment (153 if multi-segment due to UDH) |
| 55 | +- **UCS-2**: 16-bit Unicode, 70 chars/segment (67 if multi-segment) |
| 56 | +- A single non-GSM character forces the entire message to UCS-2 |
| 57 | +- `EncodedChar.isGSM7` identifies whether a character is in the GSM-7 set |
| 58 | +- `EncodedChar.codeUnits` gives the hex code units for any character |
| 59 | + |
| 60 | +### RCS Encoding |
| 61 | + |
| 62 | +- Always UTF-8 |
| 63 | +- US: billed per 160-byte "Rich" segment |
| 64 | +- International: "Basic" (<=160 bytes) or "Single" (>160 bytes), no segmentation |
| 65 | + |
| 66 | +### Browser UI Architecture |
| 67 | + |
| 68 | +Data flows through three layers: |
| 69 | +1. **segmenter.ts** — `analyzeSms()` / `analyzeRcs()` produce typed analysis objects |
| 70 | +2. **types.ts** — `SmsAnalysis`, `RcsAnalysis`, `CharDetail`, `SegmentData` interfaces |
| 71 | +3. **renderer.ts** — Pure DOM rendering functions consume analysis objects and render to target elements |
| 72 | + |
| 73 | +### Design System |
| 74 | + |
| 75 | +- Dark theme using CSS custom properties in `docs/styles/tokens.css` |
| 76 | +- Font stack: Plus Jakarta Sans (display), DM Sans (body), JetBrains Mono (code) |
| 77 | +- All colors must use CSS variables from tokens.css, never hard-coded hex values |
| 78 | +- Segment palette: `--color-seg-N-bg` / `--color-seg-N-fg` (5 rotating colors) |
| 79 | + |
| 80 | +## Code Conventions |
| 81 | + |
| 82 | +- TypeScript throughout `src/`, compiled with `tsc` |
| 83 | +- ESLint with `eslint-config-twilio-ts` (includes prettier) |
| 84 | +- Named exports preferred over default exports for browser modules |
| 85 | +- Default exports used in core library (EncodedChar, Segment, etc.) — legacy pattern |
| 86 | +- `npm run lint` must pass with zero errors before committing (warnings are OK for pre-existing issues) |
| 87 | +- Accessibility: interactive elements need `tabindex`, `role`, and `aria-label` |
| 88 | + |
| 89 | +## CI Pipeline |
| 90 | + |
| 91 | +GitHub Actions runs on every PR to `main` (`.github/workflows/test.js.yml`): |
| 92 | +1. `npm install` |
| 93 | +2. `npm run lint` — ESLint (prettier + twilio-ts rules) |
| 94 | +3. `npm test` — tsc + jest |
| 95 | + |
| 96 | +Matrix: Node 20.x, 22.x |
| 97 | + |
| 98 | +Run `npm run check` locally to mirror CI before pushing. |
| 99 | + |
| 100 | +## Pre-commit Hook |
| 101 | + |
| 102 | +Husky + lint-staged runs `eslint --fix` on staged `src/**/*.ts` files at commit time. |
| 103 | + |
| 104 | +## JIRA Conventions |
| 105 | + |
| 106 | +- **Project**: DEVED on `twilio-productivity.atlassian.net` |
| 107 | +- **Component**: "DevEd Internal" for docs projects |
| 108 | +- **Branch naming**: `{type}/{TICKET-KEY}-{description}` (e.g., `feat/DEVED-13514-restore-char-detail-view`) |
| 109 | +- **PR auto-close**: Include JIRA ticket key in PR description |
| 110 | +- **Story points**: 1 (1-4 hrs), 2 (1-2 days), 3 (2-3 days), 5 (3-5 days) |
| 111 | +- **JIRA tooling**: Use `createJiraService()` from the deved-agents repo for programmatic ticket creation |
| 112 | + |
| 113 | +## PR Workflow |
| 114 | + |
| 115 | +1. Create branch from `main` with JIRA ticket key |
| 116 | +2. Implement, run `npm run check` locally |
| 117 | +3. Push and create PR with JIRA link in description |
| 118 | +4. Follow 3-agent + 1-human review (see `docs/pr-reviews/README.md`) |
| 119 | +5. Address review feedback |
| 120 | +6. Squash and merge |
| 121 | + |
| 122 | +## E2E Testing (Playwright) |
| 123 | + |
| 124 | +Tests live in `tests/e2e/` and run against the built `docs/` site: |
| 125 | +- Config: `playwright.config.ts` — auto-serves `docs/` on port 8080 |
| 126 | +- Results/reports: `tests/e2e/results/` and `tests/e2e/reports/` (gitignored) |
| 127 | +- `tsconfig.json` includes only `src/`; `jest` ignores `tests/e2e/` — this prevents tsc and Jest from picking up Playwright files |
| 128 | + |
| 129 | +Best practices: |
| 130 | +- Use semantic selectors (`#sms-char-detail`, `.char-block`) and Playwright's auto-waiting |
| 131 | +- Check attributes directly (`toHaveAttribute('hidden', '')`) when `toBeHidden()` doesn't work for elements inside open `<details>` |
| 132 | +- Run `npm run release` before e2e tests to ensure `docs/scripts/` bundles are current |
| 133 | +- Always rebuild dist/docs artifacts before committing changes to `src/browser/` |
| 134 | + |
| 135 | +## Codex CLI Review |
| 136 | + |
| 137 | +Run `codex review --base main` for automated code review. For re-reviews after changes: |
| 138 | +```bash |
| 139 | +codex review --base main --title "PR title here" |
| 140 | +``` |
| 141 | +Capture findings in `docs/pr-reviews/<PR>/codex.md`. Mark issues as `[x]` when fixed and note which commit resolved them. |
| 142 | + |
| 143 | +## Common Pitfalls |
| 144 | + |
| 145 | +- `Segment` extends `Array` — iterating with `for...of` works but items include `UserDataHeader` entries. Filter with `isReservedChar` to get only user characters. |
| 146 | +- `EncodedChar.codeUnits` contains GSM-7 septet values for GSM characters, even in UCS-2 messages. When displaying code units for UCS-2 messages, derive UTF-16 values from `raw.charCodeAt()` instead. |
| 147 | +- `EncodedChar.isGSM7` indicates whether a character is in the GSM-7 character set, NOT the message encoding. Use `SegmentedMessage.encodingName` for the actual message encoding. |
| 148 | +- The `docs/scripts/` JS bundles are built artifacts from webpack — always run `npm run release` after changing `src/browser/` files. |
| 149 | +- `dist/` contains tsc output for the NPM package — also rebuilt by `npm run release`. |
| 150 | +- Both `docs/scripts/` and `dist/` should be committed (they are deployed artifacts). |
0 commit comments