diff --git a/.charlie/instructions/pull-request.md b/.charlie/instructions/pull-request.md new file mode 100644 index 00000000..89c9fb82 --- /dev/null +++ b/.charlie/instructions/pull-request.md @@ -0,0 +1,59 @@ +# Charlie instructions for jsx-email (next/v3 branch) + +Repo‑specific rules that keep Charlie aligned with this codebase and review preferences. Keep diffs small, mirror existing patterns, and don’t widen scope beyond the request. + +## Scope +Applies to the entire repository, with extra focus on `packages/jsx-email` and its tests. + +## Context +- Monorepo using pnpm + Moon. Most tasks are run with `pnpm moon run :`. +- Task inheritance lives in `.moon/tasks.yml`. Each project can add/override tasks in its own `moon.yml` (for example, `packages/jsx-email/moon.yml`). The root `moon.yml` defines repository tasks and is aliased as the `repo` project. +- TypeScript uses ESM with NodeNext resolution; relative imports in source include the `.js` suffix. +- Tests use Vitest; snapshots live in `.snapshots` next to tests (custom resolver). +- GitHub Actions sets `FORCE_COLOR=1` when running tests; local runs must mirror this to avoid ANSI snapshot diffs. +- Conventional Commits are the norm (e.g., `fix(jsx-email): …`). PRs should use the repository template. +- Conventional Commit scopes map to affected project name(s) under `packages/` (e.g., `(jsx-email)`, `(plugin-inline)`, `(create-jsx-email)`). When multiple projects are affected, list each name in the scope, comma‑separated with no spaces (e.g., `(plugin-inline,plugin-pretty)`). PRs should use the repository template. +- For the ongoing `next/v3` alignment work on `` / `` behavior and core correctness (tracked in #348), branch from `origin/next/v3` and open pull requests with `base` set to `next/v3` (not `main`). Mention `#348` in the PR description for traceability. + +## Rules +- [R1] Stay on task. Do not add refactors, helpers, or style tweaks outside the explicit ask. Keep diffs minimal. +- [R2] Tests and snapshots: + - Run with `FORCE_COLOR=1` to match CI. + - Never change log/ANSI‑colored snapshots to “de‑colorize” or “stabilize” output. If a log snapshot fails, fix the cause or mirror CI settings; do not rewrite the assertion shape. + - Do not introduce “snapshot normalization” helpers (e.g., projecting only parts of config objects) unless a maintainer requests it. + - Place/update snapshots under `.snapshots` alongside the test file; prefer targeted assertions plus snapshots when behavior changes intentionally. +- [R3] Writing tests for `packages/jsx-email`: + - Prefer importing from package source (e.g., `../src/index.ts`) for new tests to avoid prebuild coupling. If an existing suite imports from `dist`, keep that pattern for that suite. + - Avoid adding `// @ts-ignore` to suppress React imports; tests can rely on the React automatic JSX runtime. Don’t add new ignores. + - Follow NodeNext import style in source files (relative imports include `.js`). +- [R4] Verification commands (run locally before marking a PR Ready for changes that affect code, tests, or tooling config): + - Build artifacts used by tests: + - `pnpm moon run plugin-inline:build plugin-minify:build plugin-pretty:build` + - `pnpm moon run jsx-email:build` + - Lint: `pnpm moon run repo:lint` + - Tests (jsx-email package, mirroring the `next/v3` CI setup): `pnpm moon run jsx-email:test` + - TypeScript (package): `pnpm moon run jsx-email:tsc` + - Do not change tool configs or CI to make checks pass. + - For documentation-only or `.charlie`-only changes that do not affect CI, code, or tests, you may skip these commands, but prefer running at least `pnpm moon run repo:lint` when in doubt. +- [R4.1] Linting (must run before pushing any commits): + - Run repo linting via Moon: `pnpm moon run repo:lint`. + - Do not push if linting reports errors anywhere. Fix them or coordinate a follow‑up if they are unrelated but surfaced by your changes. + - If linting reports warnings in files you modified, resolve those warnings before pushing. + - For quick checks while iterating, you may run ESLint scoped to touched files, but always run the full `repo:lint` before the final push. +- [R5] Git & PRs: + - Branch names (from humans): `{type}/{project}/{short-desc}` — for example, `fix/jsx-email/conditional-endif-slash`. Use the package with the most changes (or the intended target) for `{project}`, and let `{short-desc}` be a descriptive phrase or a short slug. + - Conventional Commits scope = affected project name(s) from `packages/`. Examples: `fix(jsx-email): …`, `refactor(plugin-inline,plugin-pretty): …`. For multiple projects, list names comma-separated with no spaces. + - Commit messages use Conventional Commits; ≤ 72 chars in the subject; no emojis. + - PRs must use the repository template as-is — Charlie is not allowed to remove sections from the template. + - Start as Draft when work is in flux; mark Ready only after local verification passes and the description reflects the actual changes. + - Don’t add novel labels. Assign and request review from the human requester when appropriate. + +> Conditional/Raw specifics have been moved to a dedicated playbook. See `.charlie/playbooks/conditional-and-raw.md`. + +## References +1. CI workflow (test color): `.github/workflows/test-*.yml` (see `FORCE_COLOR=1` in test steps) +2. Vitest shared config: `shared/vitest.config.ts` +3. Moon tasks inheritance: `.moon/tasks.yml`; per-project tasks: `apps/*/moon.yml`, `packages/*/moon.yml`, `test/*/moon.yml`; repository tasks: `moon.yml` (project `repo`) +4. jsx-email package tasks: `packages/jsx-email/moon.yml` +5. Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0/ +6. Conditional/Raw playbook: `.charlie/playbooks/conditional-and-raw.md` diff --git a/.charlie/playbooks/conditional-and-raw.md b/.charlie/playbooks/conditional-and-raw.md new file mode 100644 index 00000000..011a47bd --- /dev/null +++ b/.charlie/playbooks/conditional-and-raw.md @@ -0,0 +1,33 @@ +# Conditional + Raw playbook (renderer and tests) — next/v3 branch + +Apply this when changing how `` or `` render (MSO/expr tokens, wrappers, or how nested Raw is inlined). + +This copy lives on the `next/v3` branch. For the ongoing alignment work on `` / `` semantics and tests (tracked in #348): +- Branch from `origin/next/v3`. +- Open pull requests with `base` set to `next/v3` (not `main`). +- Mention `#348` in the PR description so reviewers can tie the change back to the alignment effort. + +Rules +- Include targeted tests and keep snapshot updates minimal (only intentional markup diffs). +- Do not introduce token “centralization” helpers or adjacency tests unless a maintainer explicitly requests them. +- Import from source for new tests to avoid prebuild coupling: `import { Conditional, Raw, render } from '../src/index.ts'`. + +Test guidelines +- Closer/opener integrity + - Assert exactly one opener and closer for MSO: ``. + - Add a small case for the expression path (e.g., `expression="gte mso 16"`) and assert the same closer. +- No‑duplication when nesting Raw + - For ``, assert the inner payload appears exactly once and not outside the block. + - Use `lastIndexOf` for closer slicing and allow opener at index `>= 0`. +- Snapshots and colorized logs + - Run with `FORCE_COLOR=1` to match CI. Never “de‑colorize” or normalize log snapshots. + +Commands (jsx-email) +- Build artifacts some suites rely on: `pnpm moon run plugin-inline:build plugin-minify:build plugin-pretty:build && pnpm moon run jsx-email:build` +- Tests (CI‑aligned for `next/v3`): `pnpm moon run jsx-email:test` (the Moon task sets `FORCE_COLOR=1` like CI) +- TypeScript: `pnpm moon run jsx-email:tsc` + +References +- CI workflow (color): `.github/workflows/test-*.yml` (look for `FORCE_COLOR=1`) +- Shared Vitest config: `shared/vitest.config.ts` +- Package tasks: `packages/jsx-email/moon.yml` diff --git a/.charlie/playbooks/run-jsx-email-tests-like-ci.md b/.charlie/playbooks/run-jsx-email-tests-like-ci.md new file mode 100644 index 00000000..8430f4a9 --- /dev/null +++ b/.charlie/playbooks/run-jsx-email-tests-like-ci.md @@ -0,0 +1,37 @@ +# Run jsx-email tests locally exactly like CI (Moon + FORCE_COLOR) — next/v3 branch + +## Overview +Run the `packages/jsx-email` test suite locally with the same settings the `next/v3` branch uses in CI so snapshots (including ANSI color) match exactly. + +For the ongoing `next/v3` alignment work on `` / `` behavior and core correctness (tracked in #348), branch from `origin/next/v3`, open PRs with `base` set to `next/v3` (not `main`), and mention `#348` in the PR description. + +## Prerequisites +- Capabilities: GitHub + Devbox write access (local or CI). +- Tools: pnpm, Moon tasks (configured in this repo). +- Context: Some suites import from `dist/esm`, so plugin packages must be built first. + +## Steps +1. Install deps and build required artifacts + - `pnpm install` + - `pnpm moon run plugin-inline:build plugin-minify:build plugin-pretty:build` + - `pnpm moon run jsx-email:build` +2. Run tests with color forced (matches CI) + - `pnpm moon run jsx-email:test` +3. Optional: update snapshots only for intentional HTML/markup changes (never for log/ANSI deltas) + - `cd packages/jsx-email && pnpm vitest -u --config ../../shared/vitest.config.ts && cd -` +4. TypeScript check (package) + - `pnpm moon run jsx-email:tsc` + +## Verify +- Expect: `Test Files 44 passed`, `Tests 187 passed` (numbers may grow over time). +- No snapshot diffs for logs when `FORCE_COLOR=1` is set (the `jsx-email:test` Moon task configures this automatically). + +## Rollback +- If you mistakenly updated snapshots for log/ANSI output, reset them: + - `git restore --source=origin/$(git rev-parse --abbrev-ref HEAD) -- "packages/jsx-email/test/**/.snapshots/*.snap" || true` + - Or discard all local changes: `git reset --hard` + +## References +- CI workflow (color): `.github/workflows/test-*.yml` (look for `FORCE_COLOR=1`) +- Shared Vitest config: `shared/vitest.config.ts` +- Moon project tasks: `packages/jsx-email/moon.yml`