Files
openprose__prose/packages/std/delivery/email-renderer.prose.md
irl-dan 4bc41a93bb launch readiness: green CI publish path, front-door, taxonomy migration
Get the Reactor packages mergeable + publishable and the launch surfaces coherent.

CI / publish (ci-reactor-package.yml):
- Drop the deleted reactor-cradle from the workflow and remove the obsolete .mjs
  release-gate suite (.github/scripts/*reactor*.mjs + tests) entirely.
- Add per-package pack + publish jobs for @openprose/reactor, @openprose/reactor-cli,
  and @openprose/reactor-devtools (idempotent, version-from-package.json,
  reactor-v* tag-gated, provenance). The two CLI packages now have a release path.
- Fix the dangling cradle reference in tools/cli build-release-tarball.mjs;
  regenerate pnpm-lock.yaml.

Install / first-run:
- reactor-cli: @openprose/reactor moved peer -> dependency (a global install now
  pulls the SDK); @openai/agents + zod become optional peers (keyless install stays light).
- SDK README: replace non-existent *V0 imports with the real exports
  (verifyReceipt / LedgerReceipt / inspectReceiptProof / projectReceiptProof).
- CLI README + http-server comment: correct the trigger route to POST /trigger/<node>.

Front-door + taxonomy:
- Promote the Reactor-forward launch README; add the technical report at
  docs/reactor/v0.1/report.md (replacing the stale v0.1).
- Migrate SKILL.md and all packages/std + packages/co contracts off the retired
  taxonomy (kind: service -> function, kind: system deleted, ### Ensures -> ### Maintains,
  ### Criteria/### Services folded) onto the Reactor model.

Prune the dead cradle-importing examples: drop flat-tokens and
release-readiness/reactor-package-example (keeping release-readiness/src, which is tested).

Gates: build, test:reactor:offline, test:examples (10/0), test:skill (252/252) all green offline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 18:45:39 -07:00

2.3 KiB

name, kind
name kind
email-renderer function

Shape

  • self:
    • populate named slots in an email shell by generating json-render specs from structured report data
    • using only components from the provided catalog
  • delegates: none
  • prohibited:
    • writing raw HTML — all output is json-render specs; modifying the email shell — the shell is fixed infrastructure; using components not in the catalog — specs must reference only cataloged components; re-analyzing data or modifying report content — you decide slot content
    • you do not re-interpret the data

Parameters

  • report: structured report data to render (domain-specific, opaque to this contract)
  • slot_definitions: list of named slots the email shell exposes (e.g., summary, detail, footer_cta)
  • slot_catalog: reference to the component catalog — defines which json-render components are available and their accepted props

Returns

  • slots: dict of slot_name → json-render spec, one entry per slot defined in slot_definitions. The returned dict has exactly one entry per slot defined in slot_definitions; every spec is a valid json-render object ({ root, elements }) referencing only catalog components; and slots adapt to report content — empty or irrelevant sections get appropriate alternative content, not blank space.

Errors

  • empty-report: the report contains no data to render
  • unknown-slot: a slot_name is not present in slot_definitions
  • unknown-component: a spec references a component not in the catalog

Invariants

  • the email shell structure is never modified — only slot contents are produced
  • output is pure json-render specs — never raw HTML, never inline styles, never layout markup

Strategies

  • generate a json-render spec per slot — each spec is a { root, elements } object where elements reference components from the catalog; the rendering infrastructure handles converting specs to email-safe HTML
  • adapt slot content to the report — when a section has no relevant data, produce an appropriate alternative (e.g., a placeholder or positive-status message) rather than an empty spec
  • keep specs minimal — only include the data each component needs; do not duplicate report fields unnecessarily
  • when a report field is missing or null: use the catalog's default/empty-state component for that slot rather than omitting the slot entirely