@almadar/std 16.253.0 → 16.254.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/behaviors/lolo/agent/atoms/std-agent-pool.lolo +355 -0
- package/behaviors/lolo/agent/evals/eval-agent-builder.lolo +152 -0
- package/behaviors/lolo/agent/organisms/std-agent-builder.lolo +320 -26
- package/behaviors/lolo-behavior-contracts.json +1 -1
- package/behaviors/registry/agent/atoms/std-agent-context.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-fix-loop.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-memory.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-planner.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-pool.orb +1 -0
- package/behaviors/registry/agent/atoms/std-agent-proposal.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-session.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-suggestions.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-tool-call.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-tool-loop.orb +1 -1
- package/behaviors/registry/agent/atoms/std-agent-trace.orb +1 -1
- package/behaviors/registry/agent/evals/eval-agent-builder.orb +1 -0
- package/behaviors/registry/agent/organisms/std-agent-assistant.orb +1 -1
- package/behaviors/registry/agent/organisms/std-agent-builder.orb +1 -1
- package/behaviors/registry/infra/atoms/std-analytics.orb +1 -1
- package/behaviors/registry/infra/atoms/std-approval-gate.orb +1 -1
- package/behaviors/registry/infra/atoms/std-audit-capture.orb +1 -1
- package/behaviors/registry/infra/atoms/std-cache-aside.orb +1 -1
- package/behaviors/registry/infra/atoms/std-calendar-sync.orb +1 -1
- package/behaviors/registry/infra/atoms/std-cascade-on-delete.orb +1 -1
- package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +1 -1
- package/behaviors/registry/infra/atoms/std-cross-reference.orb +1 -1
- package/behaviors/registry/infra/atoms/std-data-erasure.orb +1 -1
- package/behaviors/registry/infra/atoms/std-data-import.orb +1 -1
- package/behaviors/registry/infra/atoms/std-global-search.orb +1 -1
- package/behaviors/registry/infra/atoms/std-knowledge-loop.orb +1 -1
- package/behaviors/registry/infra/atoms/std-lifecycle.orb +1 -1
- package/behaviors/registry/infra/atoms/std-migration-job.orb +1 -1
- package/behaviors/registry/infra/atoms/std-mod-queue.orb +1 -1
- package/behaviors/registry/infra/atoms/std-notification-center.orb +1 -1
- package/behaviors/registry/infra/atoms/std-notification-preferences.orb +1 -1
- package/behaviors/registry/infra/atoms/std-notify-on-event.orb +1 -1
- package/behaviors/registry/infra/atoms/std-page-search.orb +1 -1
- package/behaviors/registry/infra/atoms/std-page-watch.orb +1 -1
- package/behaviors/registry/infra/atoms/std-permission-matrix.orb +1 -1
- package/behaviors/registry/infra/atoms/std-rate-limiter.orb +1 -1
- package/behaviors/registry/infra/atoms/std-reminder-scheduler.orb +1 -1
- package/behaviors/registry/infra/atoms/std-review-cycle.orb +1 -1
- package/behaviors/registry/infra/atoms/std-row-access-control.orb +1 -1
- package/behaviors/registry/infra/atoms/std-status-lifecycle.orb +1 -1
- package/behaviors/registry/infra/organisms/std-status-lifecycle-control.orb +1 -1
- package/behaviors/registry/ml/atoms/std-data-collector.orb +1 -1
- package/behaviors/registry/ml/atoms/std-graph-builder.orb +1 -1
- package/behaviors/registry/ml/atoms/std-ml-classify.orb +1 -1
- package/behaviors/registry/ml/atoms/std-ml-infer.orb +1 -1
- package/behaviors/registry/ml/atoms/std-ml-label-capture.orb +1 -1
- package/behaviors/registry/ml/atoms/std-ml-lookup.orb +1 -1
- package/behaviors/registry/ml/atoms/std-ml-posterior.orb +1 -1
- package/behaviors/registry/ml/atoms/std-ml-similarity.orb +1 -1
- package/behaviors/registry/ml/atoms/std-tokenizer.orb +1 -1
- package/behaviors/registry/ml/atoms/std-weight-validator.orb +1 -1
- package/behaviors/registry/ml/organisms/std-escalating-decision.orb +1 -1
- package/behaviors/registry/ml/organisms/std-knowledge-tracing.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/std-avl-cosmic-zoom.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-avl-glyph.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-avl-state-machine.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-avl-transition-detail.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-avl-transition-explainer.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-behavior-view.orb +1 -1
- package/behaviors/registry/ui/avl/atoms/ui-module-card.orb +1 -1
- package/behaviors/registry/ui/avl/organisms/ui-flow-canvas.orb +1 -1
- package/behaviors/registry/ui/avl/organisms/ui-layers-panel.orb +1 -1
- package/behaviors/registry/ui/avl/organisms/ui-orb-inspector.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-app-layout.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-app-search.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-behavior-catalog.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-behavior-tour.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-board.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-book-reader.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-browse.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-calendar.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-card-grid.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-confirmation.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-date-range.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-detail-layout.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-doc-page.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-esign-request.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-event-log.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-export.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-file-store.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-filter.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-gallery.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-gantt-schedule.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-geosearch.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-graphs.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-hero.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-home.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-image-upload-multi.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-import.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-language-picker.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-media-section.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-modal-editor.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-modal.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-multi-party-flow.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-notification-panel.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-panel-launcher.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-pricing.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-proof.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-prose.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-rating-review.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-record-detail.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-recurrence.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-related.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-role-gate.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-saved-search.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-scatter.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-scoped-list.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-selection.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-site-footer.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-site-header.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-slide-deck.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-stat-band.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-stats.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-step-flow.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-steps.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-tabs.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-tag-strip.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-tag-taxonomy.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-thread.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-tree.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-version-history.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-wizard.orb +1 -1
- package/behaviors/registry/ui/core/atoms/std-workspace-layout.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-animated-graphic.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-animated-reveal.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-aside.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-atlas-image.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-atlas-panel.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-avatar.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-badge.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-box.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-button.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-card.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-center.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-checkbox.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-conditional-wrapper.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-confetti-effect.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-day-cell.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-dialog.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-divider.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-filter-pill.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-flip-container.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-game-icon.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-hstack.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-icon.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-image.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-infinite-scroll-sentinel.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-input.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-label.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-law-reference-tooltip.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-overlay.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-pattern-tile.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-presence.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-progress-bar.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-radio.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-range-slider.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-section-header.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-select.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-spacer.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-sparkline.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-spinner.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-stack.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-status-dot.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-branch.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-connection.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-flow.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-grid.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-lobe.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-mesh.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-morph.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-node.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-pulse.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-ring.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-shield.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-svg-stack.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-switch.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-text-highlight.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-textarea.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-theme-toggle.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-time-slot-cell.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-trend-indicator.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-typewriter-text.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-typography.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-video-embed.orb +1 -1
- package/behaviors/registry/ui/core/atoms/ui-vstack.orb +1 -1
- package/behaviors/registry/ui/core/molecules/std-stat-rows.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-accordion.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-activation-block.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-activity-rail.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-agent-activity-feed.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-agent-activity-row.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-agent-chat-feed.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-alert.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-animated-counter.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-bloom-quiz-block.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-branching-logic-builder.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-breadcrumb.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-calendar-grid.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-carousel.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-change-list.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-chart-legend.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-chart.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-code-block.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-command-palette.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-commit-row.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-confirm-dialog.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-connection-block.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-container.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-content-renderer.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-data-grid.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-data-list.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-date-range-picker.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-date-range-selector.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-doc-breadcrumb.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-doc-pagination.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-doc-search.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-doc-sidebar.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-doc-toc.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-document-details.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-document-panel.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-document-viewer.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-drawer.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-edge-decoration.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-emoji-picker.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-empty-state.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-error-boundary.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-error-state.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-feature-card.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-feature-grid.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-file-tree.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-filter-group.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-flex.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-flip-card.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-floating-action-button.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-floating-toolbar.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-form-actions.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-form-field.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-form-layout.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-form-section-header.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-fx-overlay.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-gantt.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-geometric-pattern.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-gradient-divider.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-graph-canvas.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-graph-view.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-grid.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-header.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-icon-button.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-import-preview-tree.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-import-progress.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-import-source-picker.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-input-group.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-jazari-state-machine.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-lightbox.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-likert-scale.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-line-chart.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-loading-state.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-map-view.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-markdown-content.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-matrix-question.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-menu.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-meter.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-modal.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-navigation.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-notification.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-number-stepper.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-option-constraint-group.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-orbital-visualization.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-page-header.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-page-transition.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-pagination.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-popover.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-positioned-canvas.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-progress-dots.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-pull-to-refresh.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-qr-scanner.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-quiz-block.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-reflection-block.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-relation-select.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-repeatable-form-section.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-reply-tree.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-rich-text-editor.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-scaled-diagram.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-search-input.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-section.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-side-panel.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-sidebar.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-signature-pad.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-simple-grid.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-skeleton.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-social-proof.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-sortable-list.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-split.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-star-rating.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-stat-display.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-swipeable-row.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-table-view.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-tabs.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-tag-input.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-tooltip.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-top-nav-item.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-upload-drop-zone.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-version-diff.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-violation-alert.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-vote-stack.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-wizard-container.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-wizard-navigation.orb +1 -1
- package/behaviors/registry/ui/core/molecules/ui-wizard-progress.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-chat-bar.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-code-runner-panel.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-dashboard-grid.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-dock-layout.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-drawer-slot.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-form-section.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-form.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-master-detail-layout.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-modal-slot.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-runtime-debugger.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-split-pane.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-stat-card.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-state-machine-view.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-subagent-trace-panel.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-tabbed-container.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-timeline.orb +1 -1
- package/behaviors/registry/ui/core/organisms/ui-toast-slot.orb +1 -1
- package/behaviors/registry/ui/core/templates/ui-auth-layout.orb +1 -1
- package/behaviors/registry/ui/core/templates/ui-counter-template.orb +1 -1
- package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +1 -1
- package/behaviors/registry/ui/core/templates/ui-generic-app-template.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-arcade-play.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-area-fill.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-audio-cue.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-camera-rig.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-chase-ai.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-choice-gate.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-coef-pad.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-curve-fog.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-dungeon-combat.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-fx-narrative.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-fx-trail.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-gate-lock.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-gather.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-gold.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-grid-tactics.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-hero-nav.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-lives.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-loop-lock.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-market-flow.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-motion-body.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-objective-reach.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-pad-lock.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-patience.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-patrol-hazard.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-pickup.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-production.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-score.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-tutorial-autodemo.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-tutorial-overlay.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-velocity-gate.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-xp.orb +1 -1
- package/behaviors/registry/ui/game/atoms/std-zone-card.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-action-palette.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-action-tile.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-canvas-2d.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-canvas.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-choice-button.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-control-button.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-control-grid.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-dialogue-bubble.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-fx-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-group.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-mesh.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-shape-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-shape.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-skinned-mesh.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-sprite-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-sprite.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-text-layer.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-draw-text.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-game-audio-cue.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-game-audio-toggle.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-game-hud.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-game-menu.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-health-bar.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-score-display.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-sequence-bar.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-stat-badge.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-state-graph.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-state-json-view.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-timer-display.orb +1 -1
- package/behaviors/registry/ui/game/atoms/ui-trait-slot.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-platformer-puzzle.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +1 -1
- package/behaviors/registry/ui/game/organisms/std-worldmap-board-2d.orb +1 -1
- package/behaviors/registry/ui/game/templates/ui-game-shell.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-arrangement.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-classify.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-compare.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-coupled-sim.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-derivation.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-diagram.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-doser.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-estimate.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-fx-cues.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-generate.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-goal-seek.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-grid-sim.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-hotspot.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-live-sim.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-measure.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-param-explorer.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-perturb.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-predict.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-sample-accumulator.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-sandbox.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-scatter-fit.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-scenario.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-sim-3d.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-slope-probe.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-speed-drill.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-stepper.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-tour-3d.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-trace-player.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-transport.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/std-learn-tree.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-algo-graph-canvas.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +1 -1
- package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +1 -1
- package/dist/behaviors-embeddings.hash.json +2 -2
- package/dist/behaviors-embeddings.json +1 -1
- package/dist/knob-embeddings.hash.json +2 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"std-notify-on-event","version":"2.0.0","description":"std-notify-on-event — cross-orbital wiring atom. Subscribes to events from another orbital (e.g. CheckoutOrbital emits OrderPlaced, OrderRecordOrbital reacts via this atom) and dispatches a notification. Use when one orbital needs to react to or be notified about events that happen in another orbital — the wiring goes through this atom's `EventOccurred` listener which the molecule renames via traitOverrides.events to the upstream event name. Dispatch gates on `guardOp`: `eq` (default) does string-equality on `triggerStatus` against the upstream event's `status` field; `gt`/`lt`/`gte`/`lte` instead numerically compare `guardField` (read from the event's `data` payload) against `guardValue`, for threshold-crossing asks such as low-stock alerts. Resolves recipient from `recipients` (first entry; multi-recipient fan-out is a future extension), falling back to `fallbackRecipient` when set, or `@user.id` otherwise. Skips dispatch when the recipient is in `suppressionList`. Delivery consults std-notification-center data before dispatching: per-person NotificationPreference rows (matched on `personId` = recipient and `eventKey` = this listener's `eventKey`, blank = all) can mute (`mode: off`), defer to the digest drain (`mode: digest`), override the channel, or impose per-user quiet hours (a 'HH:MM-HH:MM' window, blank = none); the atom-level `quietStartHour`/`quietEndHour` window and the `frequencyCapPerWeek` rolling cap (counted against dispatched NotificationRecord audit rows for the same recipient + channel) suppress likewise. Every suppression persists an honest audit row (`dispatched: false` with the reason in `error`: quiet-hours / digest-deferred / muted-by-preference / frequency-cap / no-push-subscription) which std-notification-center's digest cycle drains later. Channels: `in-app` emits the `notify` toast; `email`/`sms`/`webhook` dispatch through call-service (email.send / twilio.sendSMS / webhook.send); `push` looks up the recipient's PushSubscription row (owned by std-notification-center) and dispatches web-push via push.send (`pushTitle` falls back to `template`; `pushDeepLink`/`pushIcon` optional). The audit row's `dispatched` flag is honest — true only once the service call succeeds.","orbitals":[{"name":"NotifyOnEventOrbital","id":"orb_C9QV22BN0JTG98GYNRQKKZ8V8R","entity":{"name":"NotificationRecord","id":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","collection":"notifications","persistence":"persistent","fields":[{"name":"id","type":"string","required":true},{"name":"recipient","type":"string","default":"","description":"The identifier of the entity receiving the notification.","synonyms":"user, target, receiver, destination"},{"name":"channel","type":"string","default":"in-app","description":"The delivery method for the notification (e.g., email, SMS, in-app).","synonyms":"delivery, medium, type"},{"name":"message","type":"string","default":"","description":"The content of the notification message.","synonyms":"text, content, body"},{"name":"severity","type":"string","default":"info","description":"Indicates the importance or urgency level of the notification.","synonyms":"priority, level, importance"},{"name":"dispatched","type":"boolean","default":false,"description":"Indicates whether the notification has been successfully sent.","synonyms":"sent, delivered, status"},{"name":"error","type":"string","default":"","description":"Failure detail from the delivery service when dispatched is false, or the suppression reason (quiet-hours / digest-deferred / muted-by-preference / frequency-cap / no-push-subscription).","synonyms":"error message, failure reason, dispatch error"},{"name":"recordedAt","type":"number","default":0,"description":"Timestamp indicating when the notification record was created.","synonyms":"creation time, timestamp, date, when"},{"name":"prefMode","type":"string","default":"","description":"Scratch: effective preference mode resolved for the current dispatch (instant/digest/off).","synonyms":"resolved mode"},{"name":"prefChannel","type":"string","default":"","description":"Scratch: channel override from the matched preference row; blank = no override.","synonyms":"channel override"},{"name":"prefQuietHours","type":"string","default":"","description":"Scratch: per-user quiet-hours window \"HH:MM-HH:MM\" from the matched preference row; blank = none.","synonyms":"user quiet hours"},{"name":"pushEndpoint","type":"string","default":"","description":"Scratch: push endpoint of the recipient's subscription for the current dispatch.","synonyms":"subscription endpoint"},{"name":"pushP256dh","type":"string","default":"","description":"Scratch: p256dh key of the recipient's push subscription.","synonyms":"push key"},{"name":"pushAuth","type":"string","default":"","description":"Scratch: auth secret of the recipient's push subscription.","synonyms":"push auth"}]},"auxiliaryEntities":[{"name":"NotificationPreference","id":"ent_CP18EGX0HZG8ZRJ250DRYPW85G","collection":"notificationPreferences","persistence":"persistent","fields":[{"name":"id","type":"string","required":true},{"name":"personId","type":"string","required":true,"description":"Owner of this preference row.","synonyms":"user, owner, account"},{"name":"eventKey","type":"string","default":"","description":"Event key this preference applies to (matches the listener's eventKey); blank = all events.","synonyms":"event, trigger, subscription"},{"name":"channel","type":"string","default":"in_app","values":["in_app","email","push","slack","sms","webhook"],"description":"Channel override for this user.","synonyms":"preferred channel, delivery method"},{"name":"mode","type":"string","default":"instant","values":["instant","digest","off"],"description":"Delivery mode: instant, digest, or off.","synonyms":"delivery mode, frequency, cadence"},{"name":"quietHours","type":"string","default":"","description":"Per-user quiet-hours window as \"HH:MM-HH:MM\" (e.g. 22:00-07:00); blank = disabled.","synonyms":"do not disturb, quiet window, night mode"},{"name":"createdAt","type":"number","default":0,"description":"Timestamp indicating when this preference row was created.","synonyms":"creation time, created"},{"name":"updatedAt","type":"number","default":0,"description":"Timestamp indicating when this preference row was last updated.","synonyms":"modified, last updated"}]},{"name":"PushSubscription","id":"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M","collection":"pushSubscriptions","persistence":"persistent","fields":[{"name":"id","type":"string","required":true},{"name":"userId","type":"string","default":"","description":"Owner of this browser push subscription.","synonyms":"user, owner, account"},{"name":"endpoint","type":"string","default":"","description":"Push service endpoint URL for this subscription.","synonyms":"push url, subscription endpoint"},{"name":"p256dh","type":"string","default":"","description":"Client public key (p256dh) of the subscription.","synonyms":"public key"},{"name":"auth","type":"string","default":"","description":"Auth secret of the subscription.","synonyms":"auth secret"},{"name":"createdAt","type":"number","default":0,"description":"When this subscription was captured.","synonyms":"subscribed at, created"}]}],"traits":[{"name":"NotifyOnEventListener","id":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0","effectRow":[{"kind":"call-service","resource":"email.send"},{"kind":"call-service","resource":"push.send"},{"kind":"call-service","resource":"twilio.sendSMS"},{"kind":"call-service","resource":"webhook.send"},{"kind":"emit","resource":"NotificationDispatched"},{"kind":"fetch","resource":"NotificationPreference"},{"kind":"fetch","resource":"NotificationRecord"},{"kind":"fetch","resource":"PushSubscription"},{"kind":"persist","resource":"NotificationRecord"},{"kind":"render-ui","resource":"toast"},{"kind":"set","resource":"@entity.channel"},{"kind":"set","resource":"@entity.dispatched"},{"kind":"set","resource":"@entity.error"},{"kind":"set","resource":"@entity.message"},{"kind":"set","resource":"@entity.prefChannel"},{"kind":"set","resource":"@entity.prefMode"},{"kind":"set","resource":"@entity.prefQuietHours"},{"kind":"set","resource":"@entity.pushAuth"},{"kind":"set","resource":"@entity.pushEndpoint"},{"kind":"set","resource":"@entity.pushP256dh"},{"kind":"set","resource":"@entity.recipient"},{"kind":"set","resource":"@entity.recordedAt"},{"kind":"set","resource":"@entity.severity"}],"category":"lifecycle","linkedEntity":"NotificationRecord","linkedEntityId":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","entityRefIds":{"PushSubscription":"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M","NotificationPreference":"ent_CP18EGX0HZG8ZRJ250DRYPW85G","NotificationRecord":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH"},"emits":[{"event":"NotificationDispatched","eventId":"evt_WJSMNJTCGX68ERY0JX99ABA5HE","scope":"external","payloadSchema":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"message","type":"string"},{"name":"severity","type":"string"}]},{"event":"NOTIFY_PREFS_LOADED","eventId":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","description":"NotificationPreference rows loaded; the arm resolves the recipient's effective mode/channel/quiet-hours","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"personId","type":"string"},{"name":"eventKey","type":"string"},{"name":"mode","type":"string"},{"name":"channel","type":"string"},{"name":"quietHours","type":"string"}],"entity":"PrefRow"}]},{"event":"NOTIFY_CAP_LOADED","eventId":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","description":"Rolling 7-day NotificationRecord window loaded; the arm enforces frequencyCapPerWeek then dispatches","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"dispatched","type":"boolean"},{"name":"recordedAt","type":"number"}],"entity":"AuditRow"}]},{"event":"NOTIFY_PUSH_SUBS","eventId":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","description":"PushSubscription rows loaded; the arm picks the recipient's subscription and dispatches push.send","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"userId","type":"string"},{"name":"endpoint","type":"string"},{"name":"p256dh","type":"string"},{"name":"auth","type":"string"}],"entity":"SubRow"}]},{"event":"NOTIFY_EMAIL_SENT","eventId":"evt_QKB838ES8BCM5Q61FF45TANDHT","description":"email.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"id","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"event":"NOTIFY_EMAIL_FAILED","eventId":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","description":"email.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_SMS_SENT","eventId":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","description":"twilio.sendSMS service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"sid","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"event":"NOTIFY_SMS_FAILED","eventId":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","description":"twilio.sendSMS service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_WEBHOOK_SENT","eventId":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","description":"webhook.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"status","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"durationMs","type":"number","required":true}]},{"event":"NOTIFY_WEBHOOK_FAILED","eventId":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","description":"webhook.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_PUSH_SENT","eventId":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","description":"push.send service result — expired:true means the subscription is gone and should be pruned","tier":"secondary","payloadSchema":[{"name":"statusCode","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"expired","type":"boolean","required":true}]},{"event":"NOTIFY_PUSH_FAILED","eventId":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","description":"push.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_LOOKUP_FAILED","eventId":"evt_6433YQR8Q04BGBQD84W97V10FH","description":"A preference / cap-window / subscription fetch failed — dispatched lands false with the fetch error","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]}],"stateMachine":{"states":[{"name":"idle","isInitial":true}],"events":[{"key":"EventOccurred","id":"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW","name":"Event occurred","payloadSchema":[{"name":"data","type":"@entity(sourceEntity)"},{"name":"status","type":"string"},{"name":"id","type":"string"}],"listened":true},{"key":"NOTIFY_PREFS_LOADED","id":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","name":"Notify Prefs Loaded","description":"NotificationPreference rows loaded; the arm resolves the recipient's effective mode/channel/quiet-hours","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"personId","type":"string"},{"name":"eventKey","type":"string"},{"name":"mode","type":"string"},{"name":"channel","type":"string"},{"name":"quietHours","type":"string"}]}],"listened":true},{"key":"NOTIFY_CAP_LOADED","id":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","name":"Notify Cap Loaded","description":"Rolling 7-day NotificationRecord window loaded; the arm enforces frequencyCapPerWeek then dispatches","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"dispatched","type":"boolean"},{"name":"recordedAt","type":"number"}]}],"listened":true},{"key":"NOTIFY_PUSH_SUBS","id":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","name":"Notify Push Subs","description":"PushSubscription rows loaded; the arm picks the recipient's subscription and dispatches push.send","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"userId","type":"string"},{"name":"endpoint","type":"string"},{"name":"p256dh","type":"string"},{"name":"auth","type":"string"}]}],"listened":true},{"key":"NOTIFY_EMAIL_SENT","id":"evt_QKB838ES8BCM5Q61FF45TANDHT","name":"Notify Email Sent","description":"email.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"id","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"key":"NOTIFY_EMAIL_FAILED","id":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","name":"Notify Email Failed","description":"email.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_SMS_SENT","id":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","name":"Notify Sms Sent","description":"twilio.sendSMS service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"sid","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"key":"NOTIFY_SMS_FAILED","id":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","name":"Notify Sms Failed","description":"twilio.sendSMS service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_WEBHOOK_SENT","id":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","name":"Notify Webhook Sent","description":"webhook.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"status","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"durationMs","type":"number","required":true}]},{"key":"NOTIFY_WEBHOOK_FAILED","id":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","name":"Notify Webhook Failed","description":"webhook.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_PUSH_SENT","id":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","name":"Notify Push Sent","description":"push.send service result — expired:true means the subscription is gone and should be pruned","tier":"secondary","payloadSchema":[{"name":"statusCode","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"expired","type":"boolean","required":true}]},{"key":"NOTIFY_PUSH_FAILED","id":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","name":"Notify Push Failed","description":"push.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_LOOKUP_FAILED","id":"evt_6433YQR8Q04BGBQD84W97V10FH","name":"Notify Lookup Failed","description":"A preference / cap-window / subscription fetch failed — dispatched lands false with the fetch error","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NotificationDispatched","id":"evt_WJSMNJTCGX68ERY0JX99ABA5HE","name":"Notification dispatched","payloadSchema":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"message","type":"string"},{"name":"severity","type":"string"}]}],"transitions":[{"from":"idle","to":"idle","event":"EventOccurred","eventId":"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW","guard":["and",["or",["=","@config.coalesce","none"],["if",["=","@config.coalesce","perDispatch"],["not",["array/includes",["array/map","@prevEvents",["fn","e",["object/get","@e","event"]]],"@event.event"]],["not",["array/some","@prevEvents",["fn","e",["and",["=",["object/get","@e","event"],"@event.event"],["=",["object/get",["object/get","@e","payload",{}],"@config.coalesceKey"],["object/get","@event.payload","@config.coalesceKey"]]]]]]]],["if",["=","@config.guardOp","eq"],["or",["=","@config.triggerStatus",""],["=","@payload.status","@config.triggerStatus"]],["if",["=","@config.guardOp","gt"],[">",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"],["if",["=","@config.guardOp","lt"],["<",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"],["if",["=","@config.guardOp","gte"],[">=",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"],["<=",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"]]]]]],"effects":[["set","@entity.recipient",["if",["=",["array/len","@config.recipients"],0],["if",["not",["=","@config.fallbackRecipient",""]],"@config.fallbackRecipient","@user.id"],["array/first","@config.recipients"]]],["set","@entity.channel","@config.notifyChannel"],["set","@entity.message","@config.template"],["set","@entity.severity","@config.severity"],["set","@entity.dispatched",false],["set","@entity.recordedAt","@now"],["when",["not",["array/includes","@config.suppressionList","@entity.recipient"]],["if",["and",["not",["=","@config.quietStartHour","@config.quietEndHour"]],["if",["<","@config.quietStartHour","@config.quietEndHour"],["and",[">=",["time/hour","@now"],"@config.quietStartHour"],["<",["time/hour","@now"],"@config.quietEndHour"]],["or",[">=",["time/hour","@now"],"@config.quietStartHour"],["<",["time/hour","@now"],"@config.quietEndHour"]]]],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"quiet-hours","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["fetch","NotificationPreference",{"emit":{"failure":"NOTIFY_LOOKUP_FAILED","success":"NOTIFY_PREFS_LOADED"}}]]],["emit","NotificationDispatched",{"channel":"@entity.channel","message":"@entity.message","recipient":"@entity.recipient","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_PREFS_LOADED","eventId":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","effects":[["set","@entity.prefMode",["if",["=",["array/len",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],0],"instant",["object/get",["array/first",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],"mode"]]],["set","@entity.prefChannel",["if",["=",["array/len",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],"channel"]]],["set","@entity.prefQuietHours",["if",["=",["array/len",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],"quietHours"]]],["set","@entity.channel",["if",["=","@entity.prefChannel",""],"@entity.channel","@entity.prefChannel"]],["if",["=","@entity.prefMode","off"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"muted-by-preference","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["=","@entity.prefMode","digest"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"digest-deferred","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["and",["str/includes","@entity.prefQuietHours","-"],["!=",["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]],["if",["<",["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]],["and",[">=",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2]],["<",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]]],["or",[">=",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2]],["<",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]]]]],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"quiet-hours","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["or",["=","@entity.channel","in-app"],["=","@entity.channel","in_app"]],["do",["set","@entity.dispatched",true],["render-ui","toast",{"type":"alert","variant":"@config.severity","message":"@config.template","dismissible":true}]],["fetch","NotificationRecord",{"emit":{"failure":"NOTIFY_LOOKUP_FAILED","success":"NOTIFY_CAP_LOADED"},"filter":[">",["object/get","@entity","recordedAt"],["-","@now",604800000]]}]]]]]]},{"from":"idle","to":"idle","event":"NOTIFY_CAP_LOADED","eventId":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","effects":[["if",["and",[">","@config.frequencyCapPerWeek",0],[">=",["array/len",["array/filter","@payload.data",["fn","r",["and",["=",["object/get","@r","recipient"],"@entity.recipient"],["=",["object/get","@r","channel"],"@entity.channel"],["=",["object/get","@r","dispatched"],true]]]]],"@config.frequencyCapPerWeek"]],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"frequency-cap","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["=","@entity.channel","email"],["call-service","email","send",{"body":"@entity.message","from":"","subject":["if",["=","@config.emailSubject",""],"@entity.message","@config.emailSubject"],"to":"@entity.recipient"},{"emit":{"failure":"NOTIFY_EMAIL_FAILED","success":"NOTIFY_EMAIL_SENT"}}],["if",["=","@entity.channel","sms"],["call-service","twilio","sendSMS",{"body":"@entity.message","to":"@entity.recipient"},{"emit":{"failure":"NOTIFY_SMS_FAILED","success":"NOTIFY_SMS_SENT"}}],["if",["=","@entity.channel","push"],["fetch","PushSubscription",{"emit":{"failure":"NOTIFY_LOOKUP_FAILED","success":"NOTIFY_PUSH_SUBS"}}],["if",["not",["=","@config.webhookUrl",""]],["call-service","webhook","send",{"event":"@entity.message","payload":{"message":"@entity.message","recipient":"@entity.recipient","severity":"@entity.severity"},"secret":"@config.webhookSecret","url":"@config.webhookUrl"},{"emit":{"failure":"NOTIFY_WEBHOOK_FAILED","success":"NOTIFY_WEBHOOK_SENT"}}],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]]]]]]},{"from":"idle","to":"idle","event":"NOTIFY_PUSH_SUBS","eventId":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","effects":[["set","@entity.pushEndpoint",["if",["=",["array/len",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],"endpoint"]]],["set","@entity.pushP256dh",["if",["=",["array/len",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],"p256dh"]]],["set","@entity.pushAuth",["if",["=",["array/len",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],"auth"]]],["if",["=","@entity.pushEndpoint",""],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"no-push-subscription","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["call-service","push","send",{"subscription":{"endpoint":"@entity.pushEndpoint","keys":{"auth":"@entity.pushAuth","p256dh":"@entity.pushP256dh"}},"title":["if",["=","@config.pushTitle",""],"@entity.message","@config.pushTitle"],"body":"@entity.message","url":"@config.pushDeepLink","icon":"@config.pushIcon"},{"emit":{"failure":"NOTIFY_PUSH_FAILED","success":"NOTIFY_PUSH_SENT"}}]]]},{"from":"idle","to":"idle","event":"NOTIFY_EMAIL_SENT","eventId":"evt_QKB838ES8BCM5Q61FF45TANDHT","effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_EMAIL_FAILED","eventId":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the email notification — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_SMS_SENT","eventId":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_SMS_FAILED","eventId":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the text message — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_WEBHOOK_SENT","eventId":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","guard":["not",["=","@config.webhookUrl",""]],"effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_WEBHOOK_FAILED","eventId":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","guard":["not",["=","@config.webhookUrl",""]],"effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the webhook notification — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_PUSH_SENT","eventId":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_PUSH_FAILED","eventId":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the push notification — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_LOOKUP_FAILED","eventId":"evt_6433YQR8Q04BGBQD84W97V10FH","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't look up notification preferences — ","@payload.error"],"dismissible":true}]]}]},"config":{"suppressionList":{"type":"[string]","default":[],"label":"Suppression list","description":"Recipient ids/addresses to skip (e.g. unsubscribed users). Suppression check runs before dispatch.","synonyms":"block list, unsubscribed, opt-out list","tier":"policy","items":{"type":"string"}},"coalesceKey":{"type":"string","default":"id","label":"Which field makes two events distinct?","description":"With `coalesce: perKey`, the upstream event's payload field compared to tell repeats apart (e.g. `id` = one notification per record). Ignored otherwise.","synonyms":"dedupe key, distinct by, per record, unique field","tier":"policy"},"webhookSecret":{"type":"string","default":"","label":"Webhook secret","description":"Signing secret forwarded to the webhook service so the receiving endpoint can verify the payload. Ignored when `webhookUrl` is blank.","synonyms":"signing secret, hmac secret, webhook signature, shared secret","tier":"internal"},"quietEndHour":{"type":"number","default":0,"label":"Quiet hours end","description":"Hour of day (0-23) when the atom-level quiet window closes. Equal to `quietStartHour` = disabled.","synonyms":"do not disturb until, silence end, night mode end","tier":"policy"},"template":{"type":"string","default":"You have a new notification","label":"Message template","description":"Text shown to the recipient; supports payload interpolation","synonyms":"notification text, message body, alert text","tier":"presentation"},"sourceEntity":{"type":"entity","default":"NotificationRecord","label":"Entity of the upstream event's data","description":"The entity whose row the upstream event carries in `data`; `guardField` names a field of it.","synonyms":"source entity, event entity, data entity, row of the event","tier":"internal","refId":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH"},"quietStartHour":{"type":"number","default":0,"label":"Quiet hours start","description":"Hour of day (0-23) when the atom-level quiet window opens. Equal to `quietEndHour` = disabled. Dispatches inside the window persist an audit row (`error: quiet-hours`, dispatched:false) which std-notification-center's digest cycle drains later. Per-user quiet hours from NotificationPreference rows apply in addition.","synonyms":"quiet hours, do not disturb from, silence start, night mode start","tier":"policy"},"guardField":{"type":"string","default":"","label":"Guard field (numeric)","description":"Field read from the upstream event's `data` payload and compared against `guardValue` when `guardOp` is not `eq` (e.g. 'stockLevel', 'quantity'). Ignored when `guardOp` is `eq`.","synonyms":"threshold field, numeric field, compare field, watched field, data field","tier":"policy"},"eventKey":{"type":"string","default":"","label":"Event key for preferences","description":"Stable key naming the upstream event this listener is bound to (e.g. 'OrderPlaced'). NotificationPreference rows (std-notification-center) whose eventKey equals this key — or is blank — apply to this listener's dispatches.","synonyms":"preference key, event name, subscription key, notification topic","tier":"policy"},"guardOp":{"type":"string","default":"eq","label":"Guard comparison","description":"How to gate dispatch. `eq` (default) does string-equality via `triggerStatus` against the upstream event's `status` field, exactly as before. `gt`/`lt`/`gte`/`lte` instead numerically compare `guardField` (read from the event's `data` payload) against `guardValue` — e.g. fire only when a stock level drops below a threshold.","synonyms":"comparison operator, threshold operator, guard mode, trigger comparison, numeric gate, greater than, less than, threshold crossing","tier":"policy","values":["eq","gt","lt","gte","lte"]},"pushDeepLink":{"type":"string","default":"","label":"Push deep link","description":"In-app path opened when the recipient clicks the push notification (e.g. '/orders'). Blank = the app root.","synonyms":"click url, open on click, target path, notification link","tier":"presentation"},"fallbackRecipient":{"type":"string","default":"","label":"Fallback recipient","description":"Recipient used when `recipients` is empty, instead of the acting user. The acting-user fallback (used when this is blank) is intended for personal notifications only — set this to an ops/team address (e.g. 'ops@example.com') for system alerts like low-stock or shipping notices, so the acting user isn't notified in place of the intended audience.","synonyms":"default recipient, backup recipient, ops address, fallback address, notify default, alert owner","tier":"policy"},"webhookUrl":{"type":"string","default":"","label":"Webhook URL","description":"Destination endpoint for the webhook channel. Dispatch only fires when this is non-blank; a blank URL on channel \"webhook\" records the audit row with dispatched:false instead of crashing (a consumer misconfiguration, not a failure).","synonyms":"webhook endpoint, callback url, target url, http endpoint, notify url","tier":"policy"},"pushIcon":{"type":"string","default":"","label":"Push icon","description":"Icon URL shown on the push notification. Blank = the browser default.","synonyms":"notification icon, badge image","tier":"presentation"},"frequencyCapPerWeek":{"type":"number","default":0,"label":"Frequency cap (per week)","description":"Max dispatched sends per (channel, recipient) per rolling 7-day window, counted against dispatched NotificationRecord audit rows. 0 = uncapped. Applies to the persisted channels (email/sms/push/webhook); in-app toasts are not audited and not capped. A capped dispatch persists an audit row (`error: frequency-cap`, dispatched:false).","synonyms":"rate limit, cap, max per week, throttle, send limit","tier":"policy"},"guardValue":{"type":"number","default":0,"label":"Guard value (numeric)","description":"Threshold compared against `guardField` when `guardOp` is not `eq` (e.g. fire when stock drops below 5).","synonyms":"threshold, cutoff, limit, watermark, trigger value","tier":"policy"},"emailSubject":{"type":"string","default":"","label":"Email subject","description":"Subject line used for the email channel. Falls back to `template` when blank. Ignored for other channels.","synonyms":"subject, subject line, email title, mail subject","tier":"presentation"},"triggerStatus":{"type":"string","default":"","label":"Trigger status","description":"When `guardOp` is `eq` and this is set, dispatch only when the upstream event's `status` field equals this value (e.g. fire only when a record becomes 'approved'). Empty = fire on every subscribed event. Ignored when `guardOp` is a numeric comparison.","synonyms":"on status, when status, status filter, only when, fire on, react on status","tier":"policy"},"pushTitle":{"type":"string","default":"","label":"Push title","description":"Notification title for the push channel. Falls back to `template` when blank. Ignored for other channels.","synonyms":"notification title, push heading, alert title","tier":"presentation"},"recipients":{"type":"[string]","default":[],"label":"Recipients","description":"Recipient ids/addresses. v1.1 uses the first entry; multi-recipient fan-out lands in v1.2 (gap). When empty, falls back to `fallbackRecipient` if set, otherwise the authenticated user.","synonyms":"targets, addressees, notify to","tier":"policy","items":{"type":"string"}},"severity":{"type":"string","default":"info","label":"Severity","description":"info, success, warning, or error — controls styling","synonyms":"alert level, priority, urgency","tier":"policy"},"coalesce":{"type":"string","default":"none","label":"Collapse repeat notifications from one action?","description":"When one action raises the subscribed event several times (a bulk import, a batch save), send one notification for the whole action (`perDispatch`) or one per distinct value of `coalesceKey` (`perKey`) instead of one per event. `none` (default) notifies on every event. Scoped to a single action: the next action notifies again.","synonyms":"dedupe, deduplicate, collapse, batch notifications, one notification, bulk, coalesce, summarize, avoid spam, notification storm","tier":"policy","values":["none","perDispatch","perKey"]},"notifyChannel":{"type":"string","default":"in-app","label":"Channel","description":"Delivery channel. `in-app` (default) emits the in-app `notify` toast. `email`/`sms`/`webhook` dispatch through call-service at event time (email.send / twilio.sendSMS / webhook.send) and persist a NotificationRecord audit row with an honest `dispatched` flag: true only once the service call succeeds, false plus the failure detail in `error` otherwise. `push` looks up the recipient's PushSubscription row (captured by std-notification-center's subscribe flow) and dispatches web-push via push.send — a recipient with no subscription records the audit row undispatched (`no-push-subscription`). `webhook` requires `webhookUrl` to actually dispatch; a blank `webhookUrl` still records the audit row undispatched rather than failing. A per-user NotificationPreference row's `channel` overrides this value for that recipient.","synonyms":"delivery method, notification channel, send via, dispatch through, push notification, web push","tier":"policy","values":["in-app","email","sms","push","webhook"]}},"scope":"instance"}],"pages":[{"name":"NotifyOnEventPage","id":"pag_1JPA77KSS2WWH1002TJP3SFD0T","path":"/notify-on-event","traits":[{"ref":"NotifyOnEventListener","refId":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"}]}],"types":{"AuditRow":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"dispatched","type":"boolean"},{"name":"recordedAt","type":"number"}],"PrefRow":[{"name":"personId","type":"string"},{"name":"eventKey","type":"string"},{"name":"mode","type":"string"},{"name":"channel","type":"string"},{"name":"quietHours","type":"string"}],"SubRow":[{"name":"userId","type":"string"},{"name":"endpoint","type":"string"},{"name":"p256dh","type":"string"},{"name":"auth","type":"string"}]}}],"schemaVersion":1,"ledger":{"schemaVersion":1,"entries":{"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M":{"id":"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M","kind":"entity","bakedName":"PushSubscription","curName":"PushSubscription","renames":[],"owner":"workspace"},"ent_CP18EGX0HZG8ZRJ250DRYPW85G":{"id":"ent_CP18EGX0HZG8ZRJ250DRYPW85G","kind":"entity","bakedName":"NotificationPreference","curName":"NotificationPreference","renames":[],"owner":"workspace"},"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH":{"id":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","kind":"entity","bakedName":"NotificationRecord","curName":"NotificationRecord","renames":[],"owner":"workspace"},"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM":{"id":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","kind":"event","bakedName":"NOTIFY_PUSH_SUBS","curName":"NOTIFY_PUSH_SUBS","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_4KY8PY9C3YP1Z1MZD55S1R9S41":{"id":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","kind":"event","bakedName":"NOTIFY_PUSH_SENT","curName":"NOTIFY_PUSH_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D":{"id":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","kind":"event","bakedName":"NOTIFY_CAP_LOADED","curName":"NOTIFY_CAP_LOADED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_6433YQR8Q04BGBQD84W97V10FH":{"id":"evt_6433YQR8Q04BGBQD84W97V10FH","kind":"event","bakedName":"NOTIFY_LOOKUP_FAILED","curName":"NOTIFY_LOOKUP_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_G2ERV6BDEQPQBJD7TCB15JH16J":{"id":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","kind":"event","bakedName":"NOTIFY_PREFS_LOADED","curName":"NOTIFY_PREFS_LOADED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_HNGTE1W8CW46E9E1BVYRJAC3AR":{"id":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","kind":"event","bakedName":"NOTIFY_WEBHOOK_SENT","curName":"NOTIFY_WEBHOOK_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS":{"id":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","kind":"event","bakedName":"NOTIFY_WEBHOOK_FAILED","curName":"NOTIFY_WEBHOOK_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_QECPV4QXN3YTHG4VG3RV9QEGGS":{"id":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","kind":"event","bakedName":"NOTIFY_SMS_FAILED","curName":"NOTIFY_SMS_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_QKB838ES8BCM5Q61FF45TANDHT":{"id":"evt_QKB838ES8BCM5Q61FF45TANDHT","kind":"event","bakedName":"NOTIFY_EMAIL_SENT","curName":"NOTIFY_EMAIL_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_TV1XNFF1WDGY6YARQRQSK60KE3":{"id":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","kind":"event","bakedName":"NOTIFY_PUSH_FAILED","curName":"NOTIFY_PUSH_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_VCVWD0YX5WEJYCH3M43Y1F29H7":{"id":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","kind":"event","bakedName":"NOTIFY_EMAIL_FAILED","curName":"NOTIFY_EMAIL_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_WJSMNJTCGX68ERY0JX99ABA5HE":{"id":"evt_WJSMNJTCGX68ERY0JX99ABA5HE","kind":"event","bakedName":"NotificationDispatched","curName":"NotificationDispatched","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_WVZ299SXQHYVRJYMX9V1QFTF4N":{"id":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","kind":"event","bakedName":"NOTIFY_SMS_SENT","curName":"NOTIFY_SMS_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW":{"id":"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW","kind":"event","bakedName":"EventOccurred","curName":"EventOccurred","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"orb_C9QV22BN0JTG98GYNRQKKZ8V8R":{"id":"orb_C9QV22BN0JTG98GYNRQKKZ8V8R","kind":"orbital","bakedName":"NotifyOnEventOrbital","curName":"NotifyOnEventOrbital","renames":[],"owner":"workspace"},"pag_1JPA77KSS2WWH1002TJP3SFD0T":{"id":"pag_1JPA77KSS2WWH1002TJP3SFD0T","kind":"page","bakedName":"NotifyOnEventPage","curName":"NotifyOnEventPage","renames":[],"owner":"workspace"},"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0":{"id":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0","kind":"trait","bakedName":"NotifyOnEventListener","curName":"NotifyOnEventListener","renames":[],"owner":"workspace"}}}}
|
|
1
|
+
{"name":"std-notify-on-event","version":"2.0.0","description":"std-notify-on-event — cross-orbital wiring atom. Subscribes to events from another orbital (e.g. CheckoutOrbital emits OrderPlaced, OrderRecordOrbital reacts via this atom) and dispatches a notification. Use when one orbital needs to react to or be notified about events that happen in another orbital — the wiring goes through this atom's `EventOccurred` listener which the molecule renames via traitOverrides.events to the upstream event name. Dispatch gates on `guardOp`: `eq` (default) does string-equality on `triggerStatus` against the upstream event's `status` field; `gt`/`lt`/`gte`/`lte` instead numerically compare `guardField` (read from the event's `data` payload) against `guardValue`, for threshold-crossing asks such as low-stock alerts. Resolves recipient from `recipients` (first entry; multi-recipient fan-out is a future extension), falling back to `fallbackRecipient` when set, or `@user.id` otherwise. Skips dispatch when the recipient is in `suppressionList`. Delivery consults std-notification-center data before dispatching: per-person NotificationPreference rows (matched on `personId` = recipient and `eventKey` = this listener's `eventKey`, blank = all) can mute (`mode: off`), defer to the digest drain (`mode: digest`), override the channel, or impose per-user quiet hours (a 'HH:MM-HH:MM' window, blank = none); the atom-level `quietStartHour`/`quietEndHour` window and the `frequencyCapPerWeek` rolling cap (counted against dispatched NotificationRecord audit rows for the same recipient + channel) suppress likewise. Every suppression persists an honest audit row (`dispatched: false` with the reason in `error`: quiet-hours / digest-deferred / muted-by-preference / frequency-cap / no-push-subscription) which std-notification-center's digest cycle drains later. Channels: `in-app` emits the `notify` toast; `email`/`sms`/`webhook` dispatch through call-service (email.send / twilio.sendSMS / webhook.send); `push` looks up the recipient's PushSubscription row (owned by std-notification-center) and dispatches web-push via push.send (`pushTitle` falls back to `template`; `pushDeepLink`/`pushIcon` optional). The audit row's `dispatched` flag is honest — true only once the service call succeeds.","orbitals":[{"name":"NotifyOnEventOrbital","id":"orb_C9QV22BN0JTG98GYNRQKKZ8V8R","entity":{"name":"NotificationRecord","id":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","collection":"notifications","persistence":"persistent","fields":[{"name":"id","type":"string","required":true},{"name":"recipient","type":"string","default":"","description":"The identifier of the entity receiving the notification.","synonyms":"user, target, receiver, destination"},{"name":"channel","type":"string","default":"in-app","description":"The delivery method for the notification (e.g., email, SMS, in-app).","synonyms":"delivery, medium, type"},{"name":"message","type":"string","default":"","description":"The content of the notification message.","synonyms":"text, content, body"},{"name":"severity","type":"string","default":"info","description":"Indicates the importance or urgency level of the notification.","synonyms":"priority, level, importance"},{"name":"dispatched","type":"boolean","default":false,"description":"Indicates whether the notification has been successfully sent.","synonyms":"sent, delivered, status"},{"name":"error","type":"string","default":"","description":"Failure detail from the delivery service when dispatched is false, or the suppression reason (quiet-hours / digest-deferred / muted-by-preference / frequency-cap / no-push-subscription).","synonyms":"error message, failure reason, dispatch error"},{"name":"recordedAt","type":"number","default":0,"description":"Timestamp indicating when the notification record was created.","synonyms":"creation time, timestamp, date, when"},{"name":"prefMode","type":"string","default":"","description":"Scratch: effective preference mode resolved for the current dispatch (instant/digest/off).","synonyms":"resolved mode"},{"name":"prefChannel","type":"string","default":"","description":"Scratch: channel override from the matched preference row; blank = no override.","synonyms":"channel override"},{"name":"prefQuietHours","type":"string","default":"","description":"Scratch: per-user quiet-hours window \"HH:MM-HH:MM\" from the matched preference row; blank = none.","synonyms":"user quiet hours"},{"name":"pushEndpoint","type":"string","default":"","description":"Scratch: push endpoint of the recipient's subscription for the current dispatch.","synonyms":"subscription endpoint"},{"name":"pushP256dh","type":"string","default":"","description":"Scratch: p256dh key of the recipient's push subscription.","synonyms":"push key"},{"name":"pushAuth","type":"string","default":"","description":"Scratch: auth secret of the recipient's push subscription.","synonyms":"push auth"}]},"auxiliaryEntities":[{"name":"NotificationPreference","id":"ent_CP18EGX0HZG8ZRJ250DRYPW85G","collection":"notificationPreferences","persistence":"persistent","fields":[{"name":"id","type":"string","required":true},{"name":"personId","type":"string","required":true,"description":"Owner of this preference row.","synonyms":"user, owner, account"},{"name":"eventKey","type":"string","default":"","description":"Event key this preference applies to (matches the listener's eventKey); blank = all events.","synonyms":"event, trigger, subscription"},{"name":"channel","type":"string","default":"in_app","values":["in_app","email","push","slack","sms","webhook"],"description":"Channel override for this user.","synonyms":"preferred channel, delivery method"},{"name":"mode","type":"string","default":"instant","values":["instant","digest","off"],"description":"Delivery mode: instant, digest, or off.","synonyms":"delivery mode, frequency, cadence"},{"name":"quietHours","type":"string","default":"","description":"Per-user quiet-hours window as \"HH:MM-HH:MM\" (e.g. 22:00-07:00); blank = disabled.","synonyms":"do not disturb, quiet window, night mode"},{"name":"createdAt","type":"number","default":0,"description":"Timestamp indicating when this preference row was created.","synonyms":"creation time, created"},{"name":"updatedAt","type":"number","default":0,"description":"Timestamp indicating when this preference row was last updated.","synonyms":"modified, last updated"}]},{"name":"PushSubscription","id":"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M","collection":"pushSubscriptions","persistence":"persistent","fields":[{"name":"id","type":"string","required":true},{"name":"userId","type":"string","default":"","description":"Owner of this browser push subscription.","synonyms":"user, owner, account"},{"name":"endpoint","type":"string","default":"","description":"Push service endpoint URL for this subscription.","synonyms":"push url, subscription endpoint"},{"name":"p256dh","type":"string","default":"","description":"Client public key (p256dh) of the subscription.","synonyms":"public key"},{"name":"auth","type":"string","default":"","description":"Auth secret of the subscription.","synonyms":"auth secret"},{"name":"createdAt","type":"number","default":0,"description":"When this subscription was captured.","synonyms":"subscribed at, created"}]}],"traits":[{"name":"NotifyOnEventListener","id":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0","effectRow":[{"kind":"call-service","resource":"email.send"},{"kind":"call-service","resource":"push.send"},{"kind":"call-service","resource":"twilio.sendSMS"},{"kind":"call-service","resource":"webhook.send"},{"kind":"emit","resource":"NotificationDispatched"},{"kind":"fetch","resource":"NotificationPreference"},{"kind":"fetch","resource":"NotificationRecord"},{"kind":"fetch","resource":"PushSubscription"},{"kind":"persist","resource":"NotificationRecord"},{"kind":"render-ui","resource":"toast"},{"kind":"set","resource":"@entity.channel"},{"kind":"set","resource":"@entity.dispatched"},{"kind":"set","resource":"@entity.error"},{"kind":"set","resource":"@entity.message"},{"kind":"set","resource":"@entity.prefChannel"},{"kind":"set","resource":"@entity.prefMode"},{"kind":"set","resource":"@entity.prefQuietHours"},{"kind":"set","resource":"@entity.pushAuth"},{"kind":"set","resource":"@entity.pushEndpoint"},{"kind":"set","resource":"@entity.pushP256dh"},{"kind":"set","resource":"@entity.recipient"},{"kind":"set","resource":"@entity.recordedAt"},{"kind":"set","resource":"@entity.severity"}],"category":"lifecycle","linkedEntity":"NotificationRecord","linkedEntityId":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","entityRefIds":{"NotificationPreference":"ent_CP18EGX0HZG8ZRJ250DRYPW85G","NotificationRecord":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","PushSubscription":"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M"},"emits":[{"event":"NotificationDispatched","eventId":"evt_WJSMNJTCGX68ERY0JX99ABA5HE","scope":"external","payloadSchema":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"message","type":"string"},{"name":"severity","type":"string"}]},{"event":"NOTIFY_PREFS_LOADED","eventId":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","description":"NotificationPreference rows loaded; the arm resolves the recipient's effective mode/channel/quiet-hours","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"personId","type":"string"},{"name":"eventKey","type":"string"},{"name":"mode","type":"string"},{"name":"channel","type":"string"},{"name":"quietHours","type":"string"}],"entity":"PrefRow"}]},{"event":"NOTIFY_CAP_LOADED","eventId":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","description":"Rolling 7-day NotificationRecord window loaded; the arm enforces frequencyCapPerWeek then dispatches","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"dispatched","type":"boolean"},{"name":"recordedAt","type":"number"}],"entity":"AuditRow"}]},{"event":"NOTIFY_PUSH_SUBS","eventId":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","description":"PushSubscription rows loaded; the arm picks the recipient's subscription and dispatches push.send","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"userId","type":"string"},{"name":"endpoint","type":"string"},{"name":"p256dh","type":"string"},{"name":"auth","type":"string"}],"entity":"SubRow"}]},{"event":"NOTIFY_EMAIL_SENT","eventId":"evt_QKB838ES8BCM5Q61FF45TANDHT","description":"email.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"id","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"event":"NOTIFY_EMAIL_FAILED","eventId":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","description":"email.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_SMS_SENT","eventId":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","description":"twilio.sendSMS service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"sid","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"event":"NOTIFY_SMS_FAILED","eventId":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","description":"twilio.sendSMS service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_WEBHOOK_SENT","eventId":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","description":"webhook.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"status","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"durationMs","type":"number","required":true}]},{"event":"NOTIFY_WEBHOOK_FAILED","eventId":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","description":"webhook.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_PUSH_SENT","eventId":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","description":"push.send service result — expired:true means the subscription is gone and should be pruned","tier":"secondary","payloadSchema":[{"name":"statusCode","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"expired","type":"boolean","required":true}]},{"event":"NOTIFY_PUSH_FAILED","eventId":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","description":"push.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"NOTIFY_LOOKUP_FAILED","eventId":"evt_6433YQR8Q04BGBQD84W97V10FH","description":"A preference / cap-window / subscription fetch failed — dispatched lands false with the fetch error","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]}],"stateMachine":{"states":[{"name":"idle","isInitial":true}],"events":[{"key":"EventOccurred","id":"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW","name":"Event occurred","payloadSchema":[{"name":"data","type":"@entity(sourceEntity)"},{"name":"status","type":"string"},{"name":"id","type":"string"}],"listened":true},{"key":"NOTIFY_PREFS_LOADED","id":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","name":"Notify Prefs Loaded","description":"NotificationPreference rows loaded; the arm resolves the recipient's effective mode/channel/quiet-hours","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"personId","type":"string"},{"name":"eventKey","type":"string"},{"name":"mode","type":"string"},{"name":"channel","type":"string"},{"name":"quietHours","type":"string"}]}],"listened":true},{"key":"NOTIFY_CAP_LOADED","id":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","name":"Notify Cap Loaded","description":"Rolling 7-day NotificationRecord window loaded; the arm enforces frequencyCapPerWeek then dispatches","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"dispatched","type":"boolean"},{"name":"recordedAt","type":"number"}]}],"listened":true},{"key":"NOTIFY_PUSH_SUBS","id":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","name":"Notify Push Subs","description":"PushSubscription rows loaded; the arm picks the recipient's subscription and dispatches push.send","tier":"secondary","payloadSchema":[{"name":"data","type":"[object]","properties":[{"name":"userId","type":"string"},{"name":"endpoint","type":"string"},{"name":"p256dh","type":"string"},{"name":"auth","type":"string"}]}],"listened":true},{"key":"NOTIFY_EMAIL_SENT","id":"evt_QKB838ES8BCM5Q61FF45TANDHT","name":"Notify Email Sent","description":"email.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"id","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"key":"NOTIFY_EMAIL_FAILED","id":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","name":"Notify Email Failed","description":"email.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_SMS_SENT","id":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","name":"Notify Sms Sent","description":"twilio.sendSMS service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"sid","type":"string","required":true},{"name":"status","type":"string","required":true}]},{"key":"NOTIFY_SMS_FAILED","id":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","name":"Notify Sms Failed","description":"twilio.sendSMS service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_WEBHOOK_SENT","id":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","name":"Notify Webhook Sent","description":"webhook.send service result, flattened onto the payload by the call-service effect executor","tier":"secondary","payloadSchema":[{"name":"status","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"durationMs","type":"number","required":true}]},{"key":"NOTIFY_WEBHOOK_FAILED","id":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","name":"Notify Webhook Failed","description":"webhook.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_PUSH_SENT","id":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","name":"Notify Push Sent","description":"push.send service result — expired:true means the subscription is gone and should be pruned","tier":"secondary","payloadSchema":[{"name":"statusCode","type":"number","required":true},{"name":"ok","type":"boolean","required":true},{"name":"expired","type":"boolean","required":true}]},{"key":"NOTIFY_PUSH_FAILED","id":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","name":"Notify Push Failed","description":"push.send service call failed — dispatched lands false and error carries the service detail","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NOTIFY_LOOKUP_FAILED","id":"evt_6433YQR8Q04BGBQD84W97V10FH","name":"Notify Lookup Failed","description":"A preference / cap-window / subscription fetch failed — dispatched lands false with the fetch error","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"NotificationDispatched","id":"evt_WJSMNJTCGX68ERY0JX99ABA5HE","name":"Notification dispatched","payloadSchema":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"message","type":"string"},{"name":"severity","type":"string"}]}],"transitions":[{"from":"idle","to":"idle","event":"EventOccurred","eventId":"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW","guard":["and",["or",["=","@config.coalesce","none"],["if",["=","@config.coalesce","perDispatch"],["not",["array/includes",["array/map","@prevEvents",["fn","e",["object/get","@e","event"]]],"@event.event"]],["not",["array/some","@prevEvents",["fn","e",["and",["=",["object/get","@e","event"],"@event.event"],["=",["object/get",["object/get","@e","payload",{}],"@config.coalesceKey"],["object/get","@event.payload","@config.coalesceKey"]]]]]]]],["if",["=","@config.guardOp","eq"],["or",["=","@config.triggerStatus",""],["=","@payload.status","@config.triggerStatus"]],["if",["=","@config.guardOp","gt"],[">",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"],["if",["=","@config.guardOp","lt"],["<",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"],["if",["=","@config.guardOp","gte"],[">=",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"],["<=",["object/get","@payload.data","@config.guardField",0],"@config.guardValue"]]]]]],"effects":[["set","@entity.recipient",["if",["=",["array/len","@config.recipients"],0],["if",["not",["=","@config.fallbackRecipient",""]],"@config.fallbackRecipient","@user.id"],["array/first","@config.recipients"]]],["set","@entity.channel","@config.notifyChannel"],["set","@entity.message","@config.template"],["set","@entity.severity","@config.severity"],["set","@entity.dispatched",false],["set","@entity.recordedAt","@now"],["when",["not",["array/includes","@config.suppressionList","@entity.recipient"]],["if",["and",["not",["=","@config.quietStartHour","@config.quietEndHour"]],["if",["<","@config.quietStartHour","@config.quietEndHour"],["and",[">=",["time/hour","@now"],"@config.quietStartHour"],["<",["time/hour","@now"],"@config.quietEndHour"]],["or",[">=",["time/hour","@now"],"@config.quietStartHour"],["<",["time/hour","@now"],"@config.quietEndHour"]]]],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"quiet-hours","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["fetch","NotificationPreference",{"emit":{"failure":"NOTIFY_LOOKUP_FAILED","success":"NOTIFY_PREFS_LOADED"}}]]],["emit","NotificationDispatched",{"channel":"@entity.channel","message":"@entity.message","recipient":"@entity.recipient","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_PREFS_LOADED","eventId":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","effects":[["set","@entity.prefMode",["if",["=",["array/len",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],0],"instant",["object/get",["array/first",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],"mode"]]],["set","@entity.prefChannel",["if",["=",["array/len",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],"channel"]]],["set","@entity.prefQuietHours",["if",["=",["array/len",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","p",["and",["=",["object/get","@p","personId"],"@entity.recipient"],["or",["=",["object/get","@p","eventKey"],""],["=",["object/get","@p","eventKey"],"@config.eventKey"]]]]]],"quietHours"]]],["set","@entity.channel",["if",["=","@entity.prefChannel",""],"@entity.channel","@entity.prefChannel"]],["if",["=","@entity.prefMode","off"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"muted-by-preference","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["=","@entity.prefMode","digest"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"digest-deferred","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["and",["str/includes","@entity.prefQuietHours","-"],["!=",["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]],["if",["<",["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]],["and",[">=",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2]],["<",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]]],["or",[">=",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/first",["str/split","@entity.prefQuietHours","-"]],0,2]],["<",["str/padStart",["str/concat","",["time/hour","@now"]],2,"0"],["str/slice",["array/nth",["str/split","@entity.prefQuietHours","-"],1],0,2]]]]],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"quiet-hours","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["or",["=","@entity.channel","in-app"],["=","@entity.channel","in_app"]],["do",["set","@entity.dispatched",true],["render-ui","toast",{"type":"alert","variant":"@config.severity","message":"@config.template","dismissible":true}]],["fetch","NotificationRecord",{"emit":{"failure":"NOTIFY_LOOKUP_FAILED","success":"NOTIFY_CAP_LOADED"},"filter":[">",["object/get","@entity","recordedAt"],["-","@now",604800000]]}]]]]]]},{"from":"idle","to":"idle","event":"NOTIFY_CAP_LOADED","eventId":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","effects":[["if",["and",[">","@config.frequencyCapPerWeek",0],[">=",["array/len",["array/filter","@payload.data",["fn","r",["and",["=",["object/get","@r","recipient"],"@entity.recipient"],["=",["object/get","@r","channel"],"@entity.channel"],["=",["object/get","@r","dispatched"],true]]]]],"@config.frequencyCapPerWeek"]],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"frequency-cap","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["if",["=","@entity.channel","email"],["call-service","email","send",{"body":"@entity.message","from":"","subject":["if",["=","@config.emailSubject",""],"@entity.message","@config.emailSubject"],"to":"@entity.recipient"},{"emit":{"failure":"NOTIFY_EMAIL_FAILED","success":"NOTIFY_EMAIL_SENT"}}],["if",["=","@entity.channel","sms"],["call-service","twilio","sendSMS",{"body":"@entity.message","to":"@entity.recipient"},{"emit":{"failure":"NOTIFY_SMS_FAILED","success":"NOTIFY_SMS_SENT"}}],["if",["=","@entity.channel","push"],["fetch","PushSubscription",{"emit":{"failure":"NOTIFY_LOOKUP_FAILED","success":"NOTIFY_PUSH_SUBS"}}],["if",["not",["=","@config.webhookUrl",""]],["call-service","webhook","send",{"event":"@entity.message","payload":{"message":"@entity.message","recipient":"@entity.recipient","severity":"@entity.severity"},"secret":"@config.webhookSecret","url":"@config.webhookUrl"},{"emit":{"failure":"NOTIFY_WEBHOOK_FAILED","success":"NOTIFY_WEBHOOK_SENT"}}],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]]]]]]},{"from":"idle","to":"idle","event":"NOTIFY_PUSH_SUBS","eventId":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","effects":[["set","@entity.pushEndpoint",["if",["=",["array/len",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],"endpoint"]]],["set","@entity.pushP256dh",["if",["=",["array/len",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],"p256dh"]]],["set","@entity.pushAuth",["if",["=",["array/len",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],0],"",["object/get",["array/first",["array/filter","@payload.data",["fn","s",["=",["object/get","@s","userId"],"@entity.recipient"]]]],"auth"]]],["if",["=","@entity.pushEndpoint",""],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"no-push-subscription","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["call-service","push","send",{"subscription":{"endpoint":"@entity.pushEndpoint","keys":{"auth":"@entity.pushAuth","p256dh":"@entity.pushP256dh"}},"title":["if",["=","@config.pushTitle",""],"@entity.message","@config.pushTitle"],"body":"@entity.message","url":"@config.pushDeepLink","icon":"@config.pushIcon"},{"emit":{"failure":"NOTIFY_PUSH_FAILED","success":"NOTIFY_PUSH_SENT"}}]]]},{"from":"idle","to":"idle","event":"NOTIFY_EMAIL_SENT","eventId":"evt_QKB838ES8BCM5Q61FF45TANDHT","effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_EMAIL_FAILED","eventId":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the email notification — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_SMS_SENT","eventId":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_SMS_FAILED","eventId":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the text message — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_WEBHOOK_SENT","eventId":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","guard":["not",["=","@config.webhookUrl",""]],"effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_WEBHOOK_FAILED","eventId":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","guard":["not",["=","@config.webhookUrl",""]],"effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the webhook notification — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_PUSH_SENT","eventId":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","effects":[["set","@entity.dispatched",true],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":true,"message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}]]},{"from":"idle","to":"idle","event":"NOTIFY_PUSH_FAILED","eventId":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't send the push notification — ","@payload.error"],"dismissible":true}]]},{"from":"idle","to":"idle","event":"NOTIFY_LOOKUP_FAILED","eventId":"evt_6433YQR8Q04BGBQD84W97V10FH","effects":[["set","@entity.dispatched",false],["set","@entity.error","@payload.error"],["persist","create","NotificationRecord",{"channel":"@entity.channel","dispatched":false,"error":"@entity.error","message":"@entity.message","recipient":"@entity.recipient","recordedAt":"@now","severity":"@entity.severity"}],["render-ui","toast",{"type":"alert","variant":"error","message":["str/concat","Couldn't look up notification preferences — ","@payload.error"],"dismissible":true}]]}]},"config":{"quietStartHour":{"type":"number","default":0,"label":"Quiet hours start","description":"Hour of day (0-23) when the atom-level quiet window opens. Equal to `quietEndHour` = disabled. Dispatches inside the window persist an audit row (`error: quiet-hours`, dispatched:false) which std-notification-center's digest cycle drains later. Per-user quiet hours from NotificationPreference rows apply in addition.","synonyms":"quiet hours, do not disturb from, silence start, night mode start","tier":"policy"},"suppressionList":{"type":"[string]","default":[],"label":"Suppression list","description":"Recipient ids/addresses to skip (e.g. unsubscribed users). Suppression check runs before dispatch.","synonyms":"block list, unsubscribed, opt-out list","tier":"policy","items":{"type":"string"}},"emailSubject":{"type":"string","default":"","label":"Email subject","description":"Subject line used for the email channel. Falls back to `template` when blank. Ignored for other channels.","synonyms":"subject, subject line, email title, mail subject","tier":"presentation"},"notifyChannel":{"type":"string","default":"in-app","label":"Channel","description":"Delivery channel. `in-app` (default) emits the in-app `notify` toast. `email`/`sms`/`webhook` dispatch through call-service at event time (email.send / twilio.sendSMS / webhook.send) and persist a NotificationRecord audit row with an honest `dispatched` flag: true only once the service call succeeds, false plus the failure detail in `error` otherwise. `push` looks up the recipient's PushSubscription row (captured by std-notification-center's subscribe flow) and dispatches web-push via push.send — a recipient with no subscription records the audit row undispatched (`no-push-subscription`). `webhook` requires `webhookUrl` to actually dispatch; a blank `webhookUrl` still records the audit row undispatched rather than failing. A per-user NotificationPreference row's `channel` overrides this value for that recipient.","synonyms":"delivery method, notification channel, send via, dispatch through, push notification, web push","tier":"policy","values":["in-app","email","sms","push","webhook"]},"sourceEntity":{"type":"entity","default":"NotificationRecord","label":"Entity of the upstream event's data","description":"The entity whose row the upstream event carries in `data`; `guardField` names a field of it.","synonyms":"source entity, event entity, data entity, row of the event","tier":"internal","refId":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH"},"triggerStatus":{"type":"string","default":"","label":"Trigger status","description":"When `guardOp` is `eq` and this is set, dispatch only when the upstream event's `status` field equals this value (e.g. fire only when a record becomes 'approved'). Empty = fire on every subscribed event. Ignored when `guardOp` is a numeric comparison.","synonyms":"on status, when status, status filter, only when, fire on, react on status","tier":"policy"},"webhookSecret":{"type":"string","default":"","label":"Webhook secret","description":"Signing secret forwarded to the webhook service so the receiving endpoint can verify the payload. Ignored when `webhookUrl` is blank.","synonyms":"signing secret, hmac secret, webhook signature, shared secret","tier":"internal"},"guardOp":{"type":"string","default":"eq","label":"Guard comparison","description":"How to gate dispatch. `eq` (default) does string-equality via `triggerStatus` against the upstream event's `status` field, exactly as before. `gt`/`lt`/`gte`/`lte` instead numerically compare `guardField` (read from the event's `data` payload) against `guardValue` — e.g. fire only when a stock level drops below a threshold.","synonyms":"comparison operator, threshold operator, guard mode, trigger comparison, numeric gate, greater than, less than, threshold crossing","tier":"policy","values":["eq","gt","lt","gte","lte"]},"guardValue":{"type":"number","default":0,"label":"Guard value (numeric)","description":"Threshold compared against `guardField` when `guardOp` is not `eq` (e.g. fire when stock drops below 5).","synonyms":"threshold, cutoff, limit, watermark, trigger value","tier":"policy"},"pushIcon":{"type":"string","default":"","label":"Push icon","description":"Icon URL shown on the push notification. Blank = the browser default.","synonyms":"notification icon, badge image","tier":"presentation"},"recipients":{"type":"[string]","default":[],"label":"Recipients","description":"Recipient ids/addresses. v1.1 uses the first entry; multi-recipient fan-out lands in v1.2 (gap). When empty, falls back to `fallbackRecipient` if set, otherwise the authenticated user.","synonyms":"targets, addressees, notify to","tier":"policy","items":{"type":"string"}},"pushTitle":{"type":"string","default":"","label":"Push title","description":"Notification title for the push channel. Falls back to `template` when blank. Ignored for other channels.","synonyms":"notification title, push heading, alert title","tier":"presentation"},"coalesce":{"type":"string","default":"none","label":"Collapse repeat notifications from one action?","description":"When one action raises the subscribed event several times (a bulk import, a batch save), send one notification for the whole action (`perDispatch`) or one per distinct value of `coalesceKey` (`perKey`) instead of one per event. `none` (default) notifies on every event. Scoped to a single action: the next action notifies again.","synonyms":"dedupe, deduplicate, collapse, batch notifications, one notification, bulk, coalesce, summarize, avoid spam, notification storm","tier":"policy","values":["none","perDispatch","perKey"]},"pushDeepLink":{"type":"string","default":"","label":"Push deep link","description":"In-app path opened when the recipient clicks the push notification (e.g. '/orders'). Blank = the app root.","synonyms":"click url, open on click, target path, notification link","tier":"presentation"},"frequencyCapPerWeek":{"type":"number","default":0,"label":"Frequency cap (per week)","description":"Max dispatched sends per (channel, recipient) per rolling 7-day window, counted against dispatched NotificationRecord audit rows. 0 = uncapped. Applies to the persisted channels (email/sms/push/webhook); in-app toasts are not audited and not capped. A capped dispatch persists an audit row (`error: frequency-cap`, dispatched:false).","synonyms":"rate limit, cap, max per week, throttle, send limit","tier":"policy"},"template":{"type":"string","default":"You have a new notification","label":"Message template","description":"Text shown to the recipient; supports payload interpolation","synonyms":"notification text, message body, alert text","tier":"presentation"},"fallbackRecipient":{"type":"string","default":"","label":"Fallback recipient","description":"Recipient used when `recipients` is empty, instead of the acting user. The acting-user fallback (used when this is blank) is intended for personal notifications only — set this to an ops/team address (e.g. 'ops@example.com') for system alerts like low-stock or shipping notices, so the acting user isn't notified in place of the intended audience.","synonyms":"default recipient, backup recipient, ops address, fallback address, notify default, alert owner","tier":"policy"},"eventKey":{"type":"string","default":"","label":"Event key for preferences","description":"Stable key naming the upstream event this listener is bound to (e.g. 'OrderPlaced'). NotificationPreference rows (std-notification-center) whose eventKey equals this key — or is blank — apply to this listener's dispatches.","synonyms":"preference key, event name, subscription key, notification topic","tier":"policy"},"guardField":{"type":"string","default":"","label":"Guard field (numeric)","description":"Field read from the upstream event's `data` payload and compared against `guardValue` when `guardOp` is not `eq` (e.g. 'stockLevel', 'quantity'). Ignored when `guardOp` is `eq`.","synonyms":"threshold field, numeric field, compare field, watched field, data field","tier":"policy"},"severity":{"type":"string","default":"info","label":"Severity","description":"info, success, warning, or error — controls styling","synonyms":"alert level, priority, urgency","tier":"policy"},"coalesceKey":{"type":"string","default":"id","label":"Which field makes two events distinct?","description":"With `coalesce: perKey`, the upstream event's payload field compared to tell repeats apart (e.g. `id` = one notification per record). Ignored otherwise.","synonyms":"dedupe key, distinct by, per record, unique field","tier":"policy"},"webhookUrl":{"type":"string","default":"","label":"Webhook URL","description":"Destination endpoint for the webhook channel. Dispatch only fires when this is non-blank; a blank URL on channel \"webhook\" records the audit row with dispatched:false instead of crashing (a consumer misconfiguration, not a failure).","synonyms":"webhook endpoint, callback url, target url, http endpoint, notify url","tier":"policy"},"quietEndHour":{"type":"number","default":0,"label":"Quiet hours end","description":"Hour of day (0-23) when the atom-level quiet window closes. Equal to `quietStartHour` = disabled.","synonyms":"do not disturb until, silence end, night mode end","tier":"policy"}},"scope":"instance"}],"pages":[{"name":"NotifyOnEventPage","id":"pag_1JPA77KSS2WWH1002TJP3SFD0T","path":"/notify-on-event","traits":[{"ref":"NotifyOnEventListener","refId":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"}]}],"types":{"AuditRow":[{"name":"recipient","type":"string"},{"name":"channel","type":"string"},{"name":"dispatched","type":"boolean"},{"name":"recordedAt","type":"number"}],"PrefRow":[{"name":"personId","type":"string"},{"name":"eventKey","type":"string"},{"name":"mode","type":"string"},{"name":"channel","type":"string"},{"name":"quietHours","type":"string"}],"SubRow":[{"name":"userId","type":"string"},{"name":"endpoint","type":"string"},{"name":"p256dh","type":"string"},{"name":"auth","type":"string"}]}}],"schemaVersion":1,"ledger":{"schemaVersion":1,"entries":{"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M":{"id":"ent_BP3Z2EKMWNTEANN8DVK5J7EY3M","kind":"entity","bakedName":"PushSubscription","curName":"PushSubscription","renames":[],"owner":"workspace"},"ent_CP18EGX0HZG8ZRJ250DRYPW85G":{"id":"ent_CP18EGX0HZG8ZRJ250DRYPW85G","kind":"entity","bakedName":"NotificationPreference","curName":"NotificationPreference","renames":[],"owner":"workspace"},"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH":{"id":"ent_ZRPEA3G1130GHGK1Q0GAXQKHXH","kind":"entity","bakedName":"NotificationRecord","curName":"NotificationRecord","renames":[],"owner":"workspace"},"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM":{"id":"evt_2WXH5NQTE8X74DPQ5F5SP5JNYM","kind":"event","bakedName":"NOTIFY_PUSH_SUBS","curName":"NOTIFY_PUSH_SUBS","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_4KY8PY9C3YP1Z1MZD55S1R9S41":{"id":"evt_4KY8PY9C3YP1Z1MZD55S1R9S41","kind":"event","bakedName":"NOTIFY_PUSH_SENT","curName":"NOTIFY_PUSH_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D":{"id":"evt_4SFEXA05RF2W7X0SC3BMQJ6V8D","kind":"event","bakedName":"NOTIFY_CAP_LOADED","curName":"NOTIFY_CAP_LOADED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_6433YQR8Q04BGBQD84W97V10FH":{"id":"evt_6433YQR8Q04BGBQD84W97V10FH","kind":"event","bakedName":"NOTIFY_LOOKUP_FAILED","curName":"NOTIFY_LOOKUP_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_G2ERV6BDEQPQBJD7TCB15JH16J":{"id":"evt_G2ERV6BDEQPQBJD7TCB15JH16J","kind":"event","bakedName":"NOTIFY_PREFS_LOADED","curName":"NOTIFY_PREFS_LOADED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_HNGTE1W8CW46E9E1BVYRJAC3AR":{"id":"evt_HNGTE1W8CW46E9E1BVYRJAC3AR","kind":"event","bakedName":"NOTIFY_WEBHOOK_SENT","curName":"NOTIFY_WEBHOOK_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS":{"id":"evt_K1NYJHQ8R0MC0BA3N76D3NT4MS","kind":"event","bakedName":"NOTIFY_WEBHOOK_FAILED","curName":"NOTIFY_WEBHOOK_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_QECPV4QXN3YTHG4VG3RV9QEGGS":{"id":"evt_QECPV4QXN3YTHG4VG3RV9QEGGS","kind":"event","bakedName":"NOTIFY_SMS_FAILED","curName":"NOTIFY_SMS_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_QKB838ES8BCM5Q61FF45TANDHT":{"id":"evt_QKB838ES8BCM5Q61FF45TANDHT","kind":"event","bakedName":"NOTIFY_EMAIL_SENT","curName":"NOTIFY_EMAIL_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_TV1XNFF1WDGY6YARQRQSK60KE3":{"id":"evt_TV1XNFF1WDGY6YARQRQSK60KE3","kind":"event","bakedName":"NOTIFY_PUSH_FAILED","curName":"NOTIFY_PUSH_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_VCVWD0YX5WEJYCH3M43Y1F29H7":{"id":"evt_VCVWD0YX5WEJYCH3M43Y1F29H7","kind":"event","bakedName":"NOTIFY_EMAIL_FAILED","curName":"NOTIFY_EMAIL_FAILED","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_WJSMNJTCGX68ERY0JX99ABA5HE":{"id":"evt_WJSMNJTCGX68ERY0JX99ABA5HE","kind":"event","bakedName":"NotificationDispatched","curName":"NotificationDispatched","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_WVZ299SXQHYVRJYMX9V1QFTF4N":{"id":"evt_WVZ299SXQHYVRJYMX9V1QFTF4N","kind":"event","bakedName":"NOTIFY_SMS_SENT","curName":"NOTIFY_SMS_SENT","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW":{"id":"evt_ZS15ZY1FNBQTNPWNWSYDHEG3KW","kind":"event","bakedName":"EventOccurred","curName":"EventOccurred","renames":[],"owner":"workspace","parent":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0"},"orb_C9QV22BN0JTG98GYNRQKKZ8V8R":{"id":"orb_C9QV22BN0JTG98GYNRQKKZ8V8R","kind":"orbital","bakedName":"NotifyOnEventOrbital","curName":"NotifyOnEventOrbital","renames":[],"owner":"workspace"},"pag_1JPA77KSS2WWH1002TJP3SFD0T":{"id":"pag_1JPA77KSS2WWH1002TJP3SFD0T","kind":"page","bakedName":"NotifyOnEventPage","curName":"NotifyOnEventPage","renames":[],"owner":"workspace"},"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0":{"id":"trt_MW3FKF6WGZE8FS9PTKNNJQXMD0","kind":"trait","bakedName":"NotifyOnEventListener","curName":"NotifyOnEventListener","renames":[],"owner":"workspace"}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"std-page-search","version":"1.0.0","description":"std-page-search — runs one search on a site in a background tab: opens `searchUrl` with the query as the `queryParam` parameter, reads up to `maxResults` elements matching `resultSelector` (waiting up to `waitMs` for the results to appear), closes the tab, and reports RESULTS with the fields read from each. One search at a time: SEARCH is accepted again once RESULTS or SEARCH_FAILED is reported. It never clicks anything. Needs a host with the `page` service (a browser extension with access to the search pages).","orbitals":[{"name":"PageSearchOrbital","id":"orb_F1MGQ2T0PD0B6Y872K8QQ9ZN64","entity":{"name":"PageSearchRecord","id":"ent_QN5287B363HK1Z79HTGWP9YEZA","persistence":"runtime","fields":[{"name":"query","type":"string","default":"","description":"The search being run","synonyms":"search term, terms, topic"},{"name":"tab","type":"number","default":0,"description":"The background tab running the search; 0 = none","synonyms":"tab id"},{"name":"errorMessage","type":"string","default":"","description":"Why the last search failed; blank = none","synonyms":"error, failure reason"},{"name":"status","type":"string","default":"idle","values":["idle","searching"],"description":"Whether a search is running","synonyms":"state, busy"}]},"traits":[{"name":"PageSearch","id":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M","effectRow":[{"kind":"call-service","resource":"page.closeTab"},{"kind":"call-service","resource":"page.openTab"},{"kind":"call-service","resource":"page.query"},{"kind":"emit","resource":"RESULTS"},{"kind":"emit","resource":"SEARCH_FAILED"},{"kind":"render-ui","resource":"@config.statusSlot","resolved":false},{"kind":"set","resource":"@entity.errorMessage"},{"kind":"set","resource":"@entity.query"},{"kind":"set","resource":"@entity.status"},{"kind":"set","resource":"@entity.tab"}],"category":"interaction","linkedEntity":"PageSearchRecord","linkedEntityId":"ent_QN5287B363HK1Z79HTGWP9YEZA","entityRefIds":{"PageSearchRecord":"ent_QN5287B363HK1Z79HTGWP9YEZA"},"emits":[{"event":"TAB_OPENED","eventId":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","description":"The background tab for the search is open","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true}]},{"event":"RESULTS_READ","eventId":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","description":"The results were read from the search page","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elements","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"event":"SEARCH_CALL_FAILED","eventId":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","description":"Opening the search page or reading it failed","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"RESULTS","eventId":"evt_M00VBEFDDMPPT25JK7BC0YWVJ0","description":"What one search found: each result's element id and the fields read from it","synonyms":"search results, found, hits","tier":"primary","scope":"external","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"results","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"event":"SEARCH_FAILED","eventId":"evt_TV27D0GWG9E84XJ3SH4QB7Z790","description":"The search could not be run or read","tier":"primary","scope":"external","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"error","type":"string","required":true}]}],"stateMachine":{"states":[{"name":"idle","isInitial":true},{"name":"searching"}],"events":[{"key":"INIT","id":"evt_N03QTPXDCDPP6K047EMQ97AE8W","name":"Initialize"},{"key":"SEARCH","id":"evt_G2CG5W2X2CEH66XABK1F55H5HD","name":"Search","description":"Search the site for `query`","payloadSchema":[{"name":"query","type":"string","required":true}],"external":true,"listened":true},{"key":"TAB_OPENED","id":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","name":"Tab Opened","description":"The background tab for the search is open","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true}]},{"key":"RESULTS_READ","id":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","name":"Results Read","description":"The results were read from the search page","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elements","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"key":"SEARCH_CALL_FAILED","id":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","name":"Search Call Failed","description":"Opening the search page or reading it failed","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"RESULTS","id":"evt_M00VBEFDDMPPT25JK7BC0YWVJ0","name":"Results","description":"What one search found: each result's element id and the fields read from it","synonyms":"search results, found, hits","tier":"primary","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"results","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"key":"SEARCH_FAILED","id":"evt_TV27D0GWG9E84XJ3SH4QB7Z790","name":"Search Failed","description":"The search could not be run or read","tier":"primary","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"error","type":"string","required":true}]}],"transitions":[{"from":"idle","to":"idle","event":"INIT","eventId":"evt_N03QTPXDCDPP6K047EMQ97AE8W","effects":[["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":"Ready to search"}]]},{"from":"idle","to":"searching","event":"SEARCH","eventId":"evt_G2CG5W2X2CEH66XABK1F55H5HD","effects":[["set","@entity.query","@payload.query"],["set","@entity.tab",0],["set","@entity.status","searching"],["call-service","page","openTab",{"url":"@config.searchUrl","params":["object/set",{},"@config.queryParam","@payload.query"],"match":"@config.resultsMatch","active":false},{"emit":{"success":"TAB_OPENED","failure":"SEARCH_CALL_FAILED"}}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Searching for ","@payload.query"]}]]},{"from":"searching","to":"searching","event":"INIT","eventId":"evt_N03QTPXDCDPP6K047EMQ97AE8W","effects":[["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Searching for ","@entity.query"]}]]},{"from":"searching","to":"searching","event":"TAB_OPENED","eventId":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","effects":[["set","@entity.tab","@payload.tab"],["call-service","page","query",{"tab":"@payload.tab","selector":"@config.resultSelector","fields":"@config.fields","limit":"@config.maxResults","waitMs":"@config.waitMs"},{"emit":{"success":"RESULTS_READ","failure":"SEARCH_CALL_FAILED"}}]]},{"from":"searching","to":"idle","event":"RESULTS_READ","eventId":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","effects":[["call-service","page","closeTab",{"tab":"@payload.tab"}],["set","@entity.tab",0],["set","@entity.status","idle"],["emit","RESULTS",{"query":"@entity.query","results":"@payload.elements"}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Searched for ","@entity.query"]}]]},{"from":"searching","to":"idle","event":"SEARCH_CALL_FAILED","eventId":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","guard":[">","@entity.tab",0],"effects":[["call-service","page","closeTab",{"tab":"@entity.tab"}],["set","@entity.tab",0],["set","@entity.errorMessage","@payload.error"],["set","@entity.status","idle"],["emit","SEARCH_FAILED",{"query":"@entity.query","error":"@payload.error"}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Couldn't search: ","@payload.error"]}]]},{"from":"searching","to":"idle","event":"SEARCH_CALL_FAILED","eventId":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","guard":["==","@entity.tab",0],"effects":[["set","@entity.errorMessage","@payload.error"],["set","@entity.status","idle"],["emit","SEARCH_FAILED",{"query":"@entity.query","error":"@payload.error"}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Couldn't search: ","@payload.error"]}]]}]},"config":{"resultsMatch":{"type":"string","default":"https://example.com/search*","label":"Results pages","description":"URL match pattern the results page lies in (Chrome match-pattern syntax); the search page must match it, and the extension asks for access to exactly these pages","synonyms":"site, url pattern, results url","tier":"domain"},"waitMs":{"type":"number","default":8000,"label":"Wait for results (ms)","description":"How long to wait for the results page to load and its first result to appear","synonyms":"timeout, wait, patience","tier":"infra"},"maxResults":{"type":"number","default":10,"label":"Results per search","description":"Most results read from one search","synonyms":"limit, count, how many","tier":"policy"},"queryParam":{"type":"string","default":"q","label":"Query parameter","description":"Name of the URL parameter that carries the search terms","synonyms":"query key, search parameter","tier":"domain"},"searchUrl":{"type":"string","default":"https://example.com/search","label":"Search page","description":"URL of the site's search results page, without the query","synonyms":"search url, results page, endpoint","tier":"domain"},"fields":{"type":"Map<string,PageField>","default":{},"label":"Fields","description":"Field name to how to read it from each result: `selector` (a descendant; absent reads the result itself), `attr` (an attribute; absent reads the text) , `resolve` (the value is a URL: return it absolute), `template` (compose the value from other fields, `{name}` per field; empty when any is empty) and `required` (leave the result out until this field reads non-empty)","synonyms":"columns, properties, extract","tier":"domain","items":{"type":"object","properties":{"attr":{"name":"attr","type":"string","required":false},"required":{"name":"required","type":"boolean","required":false},"template":{"name":"template","type":"string","required":false},"selector":{"name":"selector","type":"string","required":false},"resolve":{"name":"resolve","type":"boolean","required":false}}}},"resultSelector":{"type":"string","default":".result","label":"Result selector","description":"CSS selector of one result on the results page","synonyms":"result, item, card, tile","tier":"domain"},"statusSlot":{"type":"slot","default":"main","label":"Status slot","description":"Where the atom shows its one-line status; an organism running it in the background sends it to `system`","synonyms":"status area, slot","tier":"presentation"}},"scope":"instance"}],"pages":[{"name":"PageSearchPage","id":"pag_J69PX8H4FCJ7PCDBVBN4EGE4NJ","path":"/page-search","traits":[{"ref":"PageSearch","refId":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"}]}],"types":{"PageField":[{"name":"selector","type":"string"},{"name":"attr","type":"string"},{"name":"resolve","type":"boolean"},{"name":"template","type":"string"},{"name":"required","type":"boolean"}],"PageResult":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}]}}],"schemaVersion":1,"ledger":{"schemaVersion":1,"entries":{"ent_QN5287B363HK1Z79HTGWP9YEZA":{"id":"ent_QN5287B363HK1Z79HTGWP9YEZA","kind":"entity","bakedName":"PageSearchRecord","curName":"PageSearchRecord","renames":[],"owner":"workspace"},"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6":{"id":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","kind":"event","bakedName":"TAB_OPENED","curName":"TAB_OPENED","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6":{"id":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","kind":"event","bakedName":"SEARCH_CALL_FAILED","curName":"SEARCH_CALL_FAILED","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_G2CG5W2X2CEH66XABK1F55H5HD":{"id":"evt_G2CG5W2X2CEH66XABK1F55H5HD","kind":"event","bakedName":"SEARCH","curName":"SEARCH","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G":{"id":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","kind":"event","bakedName":"RESULTS_READ","curName":"RESULTS_READ","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_M00VBEFDDMPPT25JK7BC0YWVJ0":{"id":"evt_M00VBEFDDMPPT25JK7BC0YWVJ0","kind":"event","bakedName":"RESULTS","curName":"RESULTS","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_N03QTPXDCDPP6K047EMQ97AE8W":{"id":"evt_N03QTPXDCDPP6K047EMQ97AE8W","kind":"event","bakedName":"INIT","curName":"INIT","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_TV27D0GWG9E84XJ3SH4QB7Z790":{"id":"evt_TV27D0GWG9E84XJ3SH4QB7Z790","kind":"event","bakedName":"SEARCH_FAILED","curName":"SEARCH_FAILED","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"orb_F1MGQ2T0PD0B6Y872K8QQ9ZN64":{"id":"orb_F1MGQ2T0PD0B6Y872K8QQ9ZN64","kind":"orbital","bakedName":"PageSearchOrbital","curName":"PageSearchOrbital","renames":[],"owner":"workspace"},"pag_J69PX8H4FCJ7PCDBVBN4EGE4NJ":{"id":"pag_J69PX8H4FCJ7PCDBVBN4EGE4NJ","kind":"page","bakedName":"PageSearchPage","curName":"PageSearchPage","renames":[],"owner":"workspace"},"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M":{"id":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M","kind":"trait","bakedName":"PageSearch","curName":"PageSearch","renames":[],"owner":"workspace"}}}}
|
|
1
|
+
{"name":"std-page-search","version":"1.0.0","description":"std-page-search — runs one search on a site in a background tab: opens `searchUrl` with the query as the `queryParam` parameter, reads up to `maxResults` elements matching `resultSelector` (waiting up to `waitMs` for the results to appear), closes the tab, and reports RESULTS with the fields read from each. One search at a time: SEARCH is accepted again once RESULTS or SEARCH_FAILED is reported. It never clicks anything. Needs a host with the `page` service (a browser extension with access to the search pages).","orbitals":[{"name":"PageSearchOrbital","id":"orb_F1MGQ2T0PD0B6Y872K8QQ9ZN64","entity":{"name":"PageSearchRecord","id":"ent_QN5287B363HK1Z79HTGWP9YEZA","persistence":"runtime","fields":[{"name":"query","type":"string","default":"","description":"The search being run","synonyms":"search term, terms, topic"},{"name":"tab","type":"number","default":0,"description":"The background tab running the search; 0 = none","synonyms":"tab id"},{"name":"errorMessage","type":"string","default":"","description":"Why the last search failed; blank = none","synonyms":"error, failure reason"},{"name":"status","type":"string","default":"idle","values":["idle","searching"],"description":"Whether a search is running","synonyms":"state, busy"}]},"traits":[{"name":"PageSearch","id":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M","effectRow":[{"kind":"call-service","resource":"page.closeTab"},{"kind":"call-service","resource":"page.openTab"},{"kind":"call-service","resource":"page.query"},{"kind":"emit","resource":"RESULTS"},{"kind":"emit","resource":"SEARCH_FAILED"},{"kind":"render-ui","resource":"@config.statusSlot","resolved":false},{"kind":"set","resource":"@entity.errorMessage"},{"kind":"set","resource":"@entity.query"},{"kind":"set","resource":"@entity.status"},{"kind":"set","resource":"@entity.tab"}],"category":"interaction","linkedEntity":"PageSearchRecord","linkedEntityId":"ent_QN5287B363HK1Z79HTGWP9YEZA","entityRefIds":{"PageSearchRecord":"ent_QN5287B363HK1Z79HTGWP9YEZA"},"emits":[{"event":"TAB_OPENED","eventId":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","description":"The background tab for the search is open","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true}]},{"event":"RESULTS_READ","eventId":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","description":"The results were read from the search page","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elements","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"event":"SEARCH_CALL_FAILED","eventId":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","description":"Opening the search page or reading it failed","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"RESULTS","eventId":"evt_M00VBEFDDMPPT25JK7BC0YWVJ0","description":"What one search found: each result's element id and the fields read from it","synonyms":"search results, found, hits","tier":"primary","scope":"external","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"results","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"event":"SEARCH_FAILED","eventId":"evt_TV27D0GWG9E84XJ3SH4QB7Z790","description":"The search could not be run or read","tier":"primary","scope":"external","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"error","type":"string","required":true}]}],"stateMachine":{"states":[{"name":"idle","isInitial":true},{"name":"searching"}],"events":[{"key":"INIT","id":"evt_N03QTPXDCDPP6K047EMQ97AE8W","name":"Initialize"},{"key":"SEARCH","id":"evt_G2CG5W2X2CEH66XABK1F55H5HD","name":"Search","description":"Search the site for `query`","payloadSchema":[{"name":"query","type":"string","required":true}],"external":true,"listened":true},{"key":"TAB_OPENED","id":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","name":"Tab Opened","description":"The background tab for the search is open","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true}]},{"key":"RESULTS_READ","id":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","name":"Results Read","description":"The results were read from the search page","tier":"secondary","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elements","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"key":"SEARCH_CALL_FAILED","id":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","name":"Search Call Failed","description":"Opening the search page or reading it failed","tier":"secondary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"RESULTS","id":"evt_M00VBEFDDMPPT25JK7BC0YWVJ0","name":"Results","description":"What one search found: each result's element id and the fields read from it","synonyms":"search results, found, hits","tier":"primary","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"results","type":"[object]","required":true,"properties":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"entity":"PageResult"}]},{"key":"SEARCH_FAILED","id":"evt_TV27D0GWG9E84XJ3SH4QB7Z790","name":"Search Failed","description":"The search could not be run or read","tier":"primary","payloadSchema":[{"name":"query","type":"string","required":true},{"name":"error","type":"string","required":true}]}],"transitions":[{"from":"idle","to":"idle","event":"INIT","eventId":"evt_N03QTPXDCDPP6K047EMQ97AE8W","effects":[["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":"Ready to search"}]]},{"from":"idle","to":"searching","event":"SEARCH","eventId":"evt_G2CG5W2X2CEH66XABK1F55H5HD","effects":[["set","@entity.query","@payload.query"],["set","@entity.tab",0],["set","@entity.status","searching"],["call-service","page","openTab",{"url":"@config.searchUrl","params":["object/set",{},"@config.queryParam","@payload.query"],"match":"@config.resultsMatch","active":false},{"emit":{"success":"TAB_OPENED","failure":"SEARCH_CALL_FAILED"}}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Searching for ","@payload.query"]}]]},{"from":"searching","to":"searching","event":"INIT","eventId":"evt_N03QTPXDCDPP6K047EMQ97AE8W","effects":[["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Searching for ","@entity.query"]}]]},{"from":"searching","to":"searching","event":"TAB_OPENED","eventId":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","effects":[["set","@entity.tab","@payload.tab"],["call-service","page","query",{"tab":"@payload.tab","selector":"@config.resultSelector","fields":"@config.fields","limit":"@config.maxResults","waitMs":"@config.waitMs"},{"emit":{"success":"RESULTS_READ","failure":"SEARCH_CALL_FAILED"}}]]},{"from":"searching","to":"idle","event":"RESULTS_READ","eventId":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","effects":[["call-service","page","closeTab",{"tab":"@payload.tab"}],["set","@entity.tab",0],["set","@entity.status","idle"],["emit","RESULTS",{"query":"@entity.query","results":"@payload.elements"}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Searched for ","@entity.query"]}]]},{"from":"searching","to":"idle","event":"SEARCH_CALL_FAILED","eventId":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","guard":[">","@entity.tab",0],"effects":[["call-service","page","closeTab",{"tab":"@entity.tab"}],["set","@entity.tab",0],["set","@entity.errorMessage","@payload.error"],["set","@entity.status","idle"],["emit","SEARCH_FAILED",{"query":"@entity.query","error":"@payload.error"}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Couldn't search: ","@payload.error"]}]]},{"from":"searching","to":"idle","event":"SEARCH_CALL_FAILED","eventId":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","guard":["==","@entity.tab",0],"effects":[["set","@entity.errorMessage","@payload.error"],["set","@entity.status","idle"],["emit","SEARCH_FAILED",{"query":"@entity.query","error":"@payload.error"}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Couldn't search: ","@payload.error"]}]]}]},"config":{"resultsMatch":{"type":"string","default":"https://example.com/search*","label":"Results pages","description":"URL match pattern the results page lies in (Chrome match-pattern syntax); the search page must match it, and the extension asks for access to exactly these pages","synonyms":"site, url pattern, results url","tier":"domain"},"searchUrl":{"type":"string","default":"https://example.com/search","label":"Search page","description":"URL of the site's search results page, without the query","synonyms":"search url, results page, endpoint","tier":"domain"},"resultSelector":{"type":"string","default":".result","label":"Result selector","description":"CSS selector of one result on the results page","synonyms":"result, item, card, tile","tier":"domain"},"maxResults":{"type":"number","default":10,"label":"Results per search","description":"Most results read from one search","synonyms":"limit, count, how many","tier":"policy"},"fields":{"type":"Map<string,PageField>","default":{},"label":"Fields","description":"Field name to how to read it from each result: `selector` (a descendant; absent reads the result itself), `attr` (an attribute; absent reads the text) , `resolve` (the value is a URL: return it absolute), `template` (compose the value from other fields, `{name}` per field; empty when any is empty) and `required` (leave the result out until this field reads non-empty)","synonyms":"columns, properties, extract","tier":"domain","items":{"type":"object","properties":{"template":{"name":"template","type":"string","required":false},"attr":{"name":"attr","type":"string","required":false},"resolve":{"name":"resolve","type":"boolean","required":false},"required":{"name":"required","type":"boolean","required":false},"selector":{"name":"selector","type":"string","required":false}}}},"queryParam":{"type":"string","default":"q","label":"Query parameter","description":"Name of the URL parameter that carries the search terms","synonyms":"query key, search parameter","tier":"domain"},"statusSlot":{"type":"slot","default":"main","label":"Status slot","description":"Where the atom shows its one-line status; an organism running it in the background sends it to `system`","synonyms":"status area, slot","tier":"presentation"},"waitMs":{"type":"number","default":8000,"label":"Wait for results (ms)","description":"How long to wait for the results page to load and its first result to appear","synonyms":"timeout, wait, patience","tier":"infra"}},"scope":"instance"}],"pages":[{"name":"PageSearchPage","id":"pag_J69PX8H4FCJ7PCDBVBN4EGE4NJ","path":"/page-search","traits":[{"ref":"PageSearch","refId":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"}]}],"types":{"PageField":[{"name":"selector","type":"string"},{"name":"attr","type":"string"},{"name":"resolve","type":"boolean"},{"name":"template","type":"string"},{"name":"required","type":"boolean"}],"PageResult":[{"name":"elementId","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}]}}],"schemaVersion":1,"ledger":{"schemaVersion":1,"entries":{"ent_QN5287B363HK1Z79HTGWP9YEZA":{"id":"ent_QN5287B363HK1Z79HTGWP9YEZA","kind":"entity","bakedName":"PageSearchRecord","curName":"PageSearchRecord","renames":[],"owner":"workspace"},"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6":{"id":"evt_4ZP8SHJ5SY2WZA38ABG76A6XV6","kind":"event","bakedName":"TAB_OPENED","curName":"TAB_OPENED","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6":{"id":"evt_CTVYKZSJQ6SBK9YTZ30PNPP9T6","kind":"event","bakedName":"SEARCH_CALL_FAILED","curName":"SEARCH_CALL_FAILED","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_G2CG5W2X2CEH66XABK1F55H5HD":{"id":"evt_G2CG5W2X2CEH66XABK1F55H5HD","kind":"event","bakedName":"SEARCH","curName":"SEARCH","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G":{"id":"evt_GKF9S7HHP4RV2CZ5M43BF1QX5G","kind":"event","bakedName":"RESULTS_READ","curName":"RESULTS_READ","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_M00VBEFDDMPPT25JK7BC0YWVJ0":{"id":"evt_M00VBEFDDMPPT25JK7BC0YWVJ0","kind":"event","bakedName":"RESULTS","curName":"RESULTS","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_N03QTPXDCDPP6K047EMQ97AE8W":{"id":"evt_N03QTPXDCDPP6K047EMQ97AE8W","kind":"event","bakedName":"INIT","curName":"INIT","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"evt_TV27D0GWG9E84XJ3SH4QB7Z790":{"id":"evt_TV27D0GWG9E84XJ3SH4QB7Z790","kind":"event","bakedName":"SEARCH_FAILED","curName":"SEARCH_FAILED","renames":[],"owner":"workspace","parent":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M"},"orb_F1MGQ2T0PD0B6Y872K8QQ9ZN64":{"id":"orb_F1MGQ2T0PD0B6Y872K8QQ9ZN64","kind":"orbital","bakedName":"PageSearchOrbital","curName":"PageSearchOrbital","renames":[],"owner":"workspace"},"pag_J69PX8H4FCJ7PCDBVBN4EGE4NJ":{"id":"pag_J69PX8H4FCJ7PCDBVBN4EGE4NJ","kind":"page","bakedName":"PageSearchPage","curName":"PageSearchPage","renames":[],"owner":"workspace"},"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M":{"id":"trt_4B1BYEP7RB3W5RTVH8D2SGCB0M","kind":"trait","bakedName":"PageSearch","curName":"PageSearch","renames":[],"owner":"workspace"}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"std-page-watch","version":"1.0.0","description":"std-page-watch — watches every browser tab whose URL matches `match` for elements matching `itemSelector`, and reports each element once as ITEM with the `fields` read from it, now and as the page changes. Needs a host with the `page` service (a browser extension, which asks for access to exactly the `match` pages). Each item carries its tab and element id; compose std-page-treat to hide, blur, highlight or label it.","orbitals":[{"name":"PageWatchOrbital","id":"orb_BYG2WVKRTZWDFNKRXQ6R17T4X8","entity":{"name":"PageWatchRecord","id":"ent_8DMRKA4XD6EPK030DBATNJ67TF","persistence":"runtime","fields":[{"name":"watchId","type":"string","default":"","description":"Id of the attached watch","synonyms":"watch id, subscription"},{"name":"found","type":"number","default":0,"description":"How many elements have been reported","synonyms":"count, items seen, reported"},{"name":"errorMessage","type":"string","default":"","description":"Why the watch could not be attached; blank = none","synonyms":"error, failure reason"},{"name":"status","type":"string","default":"starting","values":["starting","watching","failed"],"description":"Whether the watch is attached","synonyms":"state, watching, connected"}]},"traits":[{"name":"PageWatch","id":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP","effectRow":[{"kind":"call-service","resource":"page.watch"},{"kind":"emit","resource":"ITEM"},{"kind":"render-ui","resource":"@config.statusSlot","resolved":false},{"kind":"set","resource":"@entity.errorMessage"},{"kind":"set","resource":"@entity.found"},{"kind":"set","resource":"@entity.status"},{"kind":"set","resource":"@entity.watchId"}],"category":"lifecycle","linkedEntity":"PageWatchRecord","linkedEntityId":"ent_8DMRKA4XD6EPK030DBATNJ67TF","entityRefIds":{"PageWatchRecord":"ent_8DMRKA4XD6EPK030DBATNJ67TF"},"emits":[{"event":"WATCHING","eventId":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","description":"The watch is attached","tier":"secondary","payloadSchema":[{"name":"watchId","type":"string","required":true}]},{"event":"WATCH_FAILED","eventId":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","description":"The watch could not be attached (no page service, or no access to the pages)","tier":"primary","scope":"external","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"ITEM","eventId":"evt_BHXYTXG1CE0P79XR0XAXFWVSE5","description":"One matching element, reported once, with the fields read from it","synonyms":"element found, item seen, new item","tier":"primary","scope":"external","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elementId","type":"string","required":true},{"name":"url","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}]}],"stateMachine":{"states":[{"name":"active","isInitial":true}],"events":[{"key":"INIT","id":"evt_WMNQKDMZB3FNHP8Q18FSATWDYE","name":"Initialize"},{"key":"WATCHING","id":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","name":"Watching","description":"The watch is attached","tier":"secondary","payloadSchema":[{"name":"watchId","type":"string","required":true}]},{"key":"WATCH_FAILED","id":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","name":"Watch Failed","description":"The watch could not be attached (no page service, or no access to the pages)","tier":"primary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"ITEM_FOUND","id":"evt_F35Z8T9JMZSAFM1FA8H20PCTJ7","name":"Item Found","description":"One matching element, delivered by the page service","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elementId","type":"string","required":true},{"name":"url","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"external":true,"listened":true},{"key":"ITEM","id":"evt_BHXYTXG1CE0P79XR0XAXFWVSE5","name":"Item","description":"One matching element, reported once, with the fields read from it","synonyms":"element found, item seen, new item","tier":"primary","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elementId","type":"string","required":true},{"name":"url","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}]}],"transitions":[{"from":"active","to":"active","event":"INIT","eventId":"evt_WMNQKDMZB3FNHP8Q18FSATWDYE","effects":[["call-service","page","watch",{"match":"@config.match","selector":"@config.itemSelector","fields":"@config.fields","event":"@config.itemEvent"},{"emit":{"success":"WATCHING","failure":"WATCH_FAILED"}}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":"Connecting to the pages…"}]]},{"from":"active","to":"active","event":"WATCHING","eventId":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","effects":[["set","@entity.watchId","@payload.watchId"],["set","@entity.status","watching"],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Watching ","@config.match"]}]]},{"from":"active","to":"active","event":"WATCH_FAILED","eventId":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","effects":[["set","@entity.errorMessage","@payload.error"],["set","@entity.status","failed"],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Can't watch these pages: ","@payload.error"]}]]},{"from":"active","to":"active","event":"ITEM_FOUND","eventId":"evt_F35Z8T9JMZSAFM1FA8H20PCTJ7","effects":[["set","@entity.found",["+","@entity.found",1]],["emit","ITEM",{"tab":"@payload.tab","elementId":"@payload.elementId","url":"@payload.url","fields":"@payload.fields"}]]}]},"config":{"
|
|
1
|
+
{"name":"std-page-watch","version":"1.0.0","description":"std-page-watch — watches every browser tab whose URL matches `match` for elements matching `itemSelector`, and reports each element once as ITEM with the `fields` read from it, now and as the page changes. Needs a host with the `page` service (a browser extension, which asks for access to exactly the `match` pages). Each item carries its tab and element id; compose std-page-treat to hide, blur, highlight or label it.","orbitals":[{"name":"PageWatchOrbital","id":"orb_BYG2WVKRTZWDFNKRXQ6R17T4X8","entity":{"name":"PageWatchRecord","id":"ent_8DMRKA4XD6EPK030DBATNJ67TF","persistence":"runtime","fields":[{"name":"watchId","type":"string","default":"","description":"Id of the attached watch","synonyms":"watch id, subscription"},{"name":"found","type":"number","default":0,"description":"How many elements have been reported","synonyms":"count, items seen, reported"},{"name":"errorMessage","type":"string","default":"","description":"Why the watch could not be attached; blank = none","synonyms":"error, failure reason"},{"name":"status","type":"string","default":"starting","values":["starting","watching","failed"],"description":"Whether the watch is attached","synonyms":"state, watching, connected"}]},"traits":[{"name":"PageWatch","id":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP","effectRow":[{"kind":"call-service","resource":"page.watch"},{"kind":"emit","resource":"ITEM"},{"kind":"render-ui","resource":"@config.statusSlot","resolved":false},{"kind":"set","resource":"@entity.errorMessage"},{"kind":"set","resource":"@entity.found"},{"kind":"set","resource":"@entity.status"},{"kind":"set","resource":"@entity.watchId"}],"category":"lifecycle","linkedEntity":"PageWatchRecord","linkedEntityId":"ent_8DMRKA4XD6EPK030DBATNJ67TF","entityRefIds":{"PageWatchRecord":"ent_8DMRKA4XD6EPK030DBATNJ67TF"},"emits":[{"event":"WATCHING","eventId":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","description":"The watch is attached","tier":"secondary","payloadSchema":[{"name":"watchId","type":"string","required":true}]},{"event":"WATCH_FAILED","eventId":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","description":"The watch could not be attached (no page service, or no access to the pages)","tier":"primary","scope":"external","payloadSchema":[{"name":"error","type":"string","required":true}]},{"event":"ITEM","eventId":"evt_BHXYTXG1CE0P79XR0XAXFWVSE5","description":"One matching element, reported once, with the fields read from it","synonyms":"element found, item seen, new item","tier":"primary","scope":"external","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elementId","type":"string","required":true},{"name":"url","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}]}],"stateMachine":{"states":[{"name":"active","isInitial":true}],"events":[{"key":"INIT","id":"evt_WMNQKDMZB3FNHP8Q18FSATWDYE","name":"Initialize"},{"key":"WATCHING","id":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","name":"Watching","description":"The watch is attached","tier":"secondary","payloadSchema":[{"name":"watchId","type":"string","required":true}]},{"key":"WATCH_FAILED","id":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","name":"Watch Failed","description":"The watch could not be attached (no page service, or no access to the pages)","tier":"primary","payloadSchema":[{"name":"error","type":"string","required":true}]},{"key":"ITEM_FOUND","id":"evt_F35Z8T9JMZSAFM1FA8H20PCTJ7","name":"Item Found","description":"One matching element, delivered by the page service","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elementId","type":"string","required":true},{"name":"url","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}],"external":true,"listened":true},{"key":"ITEM","id":"evt_BHXYTXG1CE0P79XR0XAXFWVSE5","name":"Item","description":"One matching element, reported once, with the fields read from it","synonyms":"element found, item seen, new item","tier":"primary","payloadSchema":[{"name":"tab","type":"number","required":true},{"name":"elementId","type":"string","required":true},{"name":"url","type":"string","required":true},{"name":"fields","type":"Map<string,string>"}]}],"transitions":[{"from":"active","to":"active","event":"INIT","eventId":"evt_WMNQKDMZB3FNHP8Q18FSATWDYE","effects":[["call-service","page","watch",{"match":"@config.match","selector":"@config.itemSelector","fields":"@config.fields","event":"@config.itemEvent"},{"emit":{"success":"WATCHING","failure":"WATCH_FAILED"}}],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":"Connecting to the pages…"}]]},{"from":"active","to":"active","event":"WATCHING","eventId":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","effects":[["set","@entity.watchId","@payload.watchId"],["set","@entity.status","watching"],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Watching ","@config.match"]}]]},{"from":"active","to":"active","event":"WATCH_FAILED","eventId":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","effects":[["set","@entity.errorMessage","@payload.error"],["set","@entity.status","failed"],["render-ui","@config.statusSlot",{"type":"typography","variant":"body","role":"status","content":["str/concat","Can't watch these pages: ","@payload.error"]}]]},{"from":"active","to":"active","event":"ITEM_FOUND","eventId":"evt_F35Z8T9JMZSAFM1FA8H20PCTJ7","effects":[["set","@entity.found",["+","@entity.found",1]],["emit","ITEM",{"tab":"@payload.tab","elementId":"@payload.elementId","url":"@payload.url","fields":"@payload.fields"}]]}]},"config":{"fields":{"type":"Map<string,PageField>","default":{},"label":"Fields","description":"Field name to how to read it from each element: `selector` (a descendant; absent reads the element itself), `attr` (an attribute; absent reads the text) , `resolve` (the value is a URL: return it absolute), `template` (compose the value from other fields, `{name}` per field; empty when any is empty) and `required` (leave the element out until this field reads non-empty — a placeholder is reported once it fills in)","synonyms":"columns, properties, extract, read","tier":"domain","items":{"type":"object","properties":{"resolve":{"name":"resolve","type":"boolean","required":false},"attr":{"name":"attr","type":"string","required":false},"selector":{"name":"selector","type":"string","required":false},"required":{"name":"required","type":"boolean","required":false},"template":{"name":"template","type":"string","required":false}}}},"match":{"type":"string","default":"https://example.com/*","label":"Pages","description":"URL match pattern of the tabs to watch, in Chrome match-pattern syntax (`<scheme>://<host>/<path>` with `*` wildcards)","synonyms":"site, url pattern, pages, domain","tier":"domain"},"itemEvent":{"type":"event","default":"PageWatch.ITEM_FOUND","label":"Item input","description":"The declared input each element arrives as; it follows the trait when a composer renames it","tier":"internal"},"itemSelector":{"type":"string","default":".item","label":"Item selector","description":"CSS selector of the elements to report","synonyms":"selector, element, card, tile, row","tier":"domain"},"statusSlot":{"type":"slot","default":"main","label":"Status slot","description":"Where the atom shows its one-line status; an organism running it in the background sends it to `system`","synonyms":"status area, slot","tier":"presentation"}},"scope":"instance"}],"pages":[{"name":"PageWatchPage","id":"pag_8CWXQJNWG3Y81VB4AZWAXRAQYE","path":"/page-watch","traits":[{"ref":"PageWatch","refId":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP"}]}],"types":{"PageField":[{"name":"selector","type":"string"},{"name":"attr","type":"string"},{"name":"resolve","type":"boolean"},{"name":"template","type":"string"},{"name":"required","type":"boolean"}]}}],"schemaVersion":1,"ledger":{"schemaVersion":1,"entries":{"ent_8DMRKA4XD6EPK030DBATNJ67TF":{"id":"ent_8DMRKA4XD6EPK030DBATNJ67TF","kind":"entity","bakedName":"PageWatchRecord","curName":"PageWatchRecord","renames":[],"owner":"workspace"},"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ":{"id":"evt_4G5N5XX5Y2JZ1A2VTJQYTSA3FQ","kind":"event","bakedName":"WATCH_FAILED","curName":"WATCH_FAILED","renames":[],"owner":"workspace","parent":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP"},"evt_BHXYTXG1CE0P79XR0XAXFWVSE5":{"id":"evt_BHXYTXG1CE0P79XR0XAXFWVSE5","kind":"event","bakedName":"ITEM","curName":"ITEM","renames":[],"owner":"workspace","parent":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP"},"evt_F35Z8T9JMZSAFM1FA8H20PCTJ7":{"id":"evt_F35Z8T9JMZSAFM1FA8H20PCTJ7","kind":"event","bakedName":"ITEM_FOUND","curName":"ITEM_FOUND","renames":[],"owner":"workspace","parent":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP"},"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5":{"id":"evt_MQAGC8FYDPZ6VC7DGEJBBFNAN5","kind":"event","bakedName":"WATCHING","curName":"WATCHING","renames":[],"owner":"workspace","parent":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP"},"evt_WMNQKDMZB3FNHP8Q18FSATWDYE":{"id":"evt_WMNQKDMZB3FNHP8Q18FSATWDYE","kind":"event","bakedName":"INIT","curName":"INIT","renames":[],"owner":"workspace","parent":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP"},"orb_BYG2WVKRTZWDFNKRXQ6R17T4X8":{"id":"orb_BYG2WVKRTZWDFNKRXQ6R17T4X8","kind":"orbital","bakedName":"PageWatchOrbital","curName":"PageWatchOrbital","renames":[],"owner":"workspace"},"pag_8CWXQJNWG3Y81VB4AZWAXRAQYE":{"id":"pag_8CWXQJNWG3Y81VB4AZWAXRAQYE","kind":"page","bakedName":"PageWatchPage","curName":"PageWatchPage","renames":[],"owner":"workspace"},"trt_03E8QQKMRFTC7JRVG8EF3D4XBP":{"id":"trt_03E8QQKMRFTC7JRVG8EF3D4XBP","kind":"trait","bakedName":"PageWatch","curName":"PageWatch","renames":[],"owner":"workspace"}}}}
|