graphrefly 0.8.0__tar.gz → 0.9.0__tar.gz

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.
Files changed (293) hide show
  1. {graphrefly-0.8.0 → graphrefly-0.9.0}/CHANGELOG.md +8 -0
  2. {graphrefly-0.8.0 → graphrefly-0.9.0}/PKG-INFO +1 -1
  3. {graphrefly-0.8.0 → graphrefly-0.9.0}/docs/optimizations.md +3 -0
  4. {graphrefly-0.8.0 → graphrefly-0.9.0}/docs/roadmap.md +10 -6
  5. {graphrefly-0.8.0 → graphrefly-0.9.0}/pyproject.toml +1 -1
  6. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/dynamic_node.py +8 -4
  7. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/node.py +8 -7
  8. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/protocol.py +1 -1
  9. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/__init__.py +11 -1
  10. graphrefly-0.9.0/src/graphrefly/patterns/graphspec.py +1212 -0
  11. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/reduction.py +53 -2
  12. graphrefly-0.9.0/tests/test_graphspec.py +612 -0
  13. {graphrefly-0.8.0 → graphrefly-0.9.0}/.claude/skills/dev-dispatch/SKILL.md +0 -0
  14. {graphrefly-0.8.0 → graphrefly-0.9.0}/.claude/skills/parity/SKILL.md +0 -0
  15. {graphrefly-0.8.0 → graphrefly-0.9.0}/.claude/skills/qa/SKILL.md +0 -0
  16. {graphrefly-0.8.0 → graphrefly-0.9.0}/.gemini/skills/dev-dispatch/SKILL.md +0 -0
  17. {graphrefly-0.8.0 → graphrefly-0.9.0}/.gemini/skills/parity/SKILL.md +0 -0
  18. {graphrefly-0.8.0 → graphrefly-0.9.0}/.github/workflows/pages.yml +0 -0
  19. {graphrefly-0.8.0 → graphrefly-0.9.0}/.github/workflows/release.yml +0 -0
  20. {graphrefly-0.8.0 → graphrefly-0.9.0}/.gitignore +0 -0
  21. {graphrefly-0.8.0 → graphrefly-0.9.0}/.mise.toml +0 -0
  22. {graphrefly-0.8.0 → graphrefly-0.9.0}/CLAUDE.md +0 -0
  23. {graphrefly-0.8.0 → graphrefly-0.9.0}/CONTRIBUTING.md +0 -0
  24. {graphrefly-0.8.0 → graphrefly-0.9.0}/GEMINI.md +0 -0
  25. {graphrefly-0.8.0 → graphrefly-0.9.0}/LICENSE +0 -0
  26. {graphrefly-0.8.0 → graphrefly-0.9.0}/README.md +0 -0
  27. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/DESIGN-ARCHIVE-INDEX.md +0 -0
  28. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-access-control-actor-guard.md +0 -0
  29. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-cross-repo-implementation-audit.md +0 -0
  30. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-demo-test-strategy.md +0 -0
  31. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-graphrefly-spec-design.md +0 -0
  32. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-serialization-memory-footprint.md +0 -0
  33. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-tier2-parity-nonlocal-forward-inner.md +0 -0
  34. {graphrefly-0.8.0 → graphrefly-0.9.0}/archive/docs/SESSION-universal-reduction-layer.md +0 -0
  35. {graphrefly-0.8.0 → graphrefly-0.9.0}/benchmarks/py-baseline.json +0 -0
  36. {graphrefly-0.8.0 → graphrefly-0.9.0}/docs/ADAPTER-CONTRACT.md +0 -0
  37. {graphrefly-0.8.0 → graphrefly-0.9.0}/docs/benchmark.md +0 -0
  38. {graphrefly-0.8.0 → graphrefly-0.9.0}/docs/docs-guidance.md +0 -0
  39. {graphrefly-0.8.0 → graphrefly-0.9.0}/docs/test-guidance.md +0 -0
  40. {graphrefly-0.8.0 → graphrefly-0.9.0}/examples/README.md +0 -0
  41. {graphrefly-0.8.0 → graphrefly-0.9.0}/examples/basic_counter.py +0 -0
  42. {graphrefly-0.8.0 → graphrefly-0.9.0}/llms.txt +0 -0
  43. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/__init__.py +0 -0
  44. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/compat/__init__.py +0 -0
  45. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/compat/async_utils.py +0 -0
  46. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/compat/asyncio_runner.py +0 -0
  47. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/compat/trio_runner.py +0 -0
  48. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/__init__.py +0 -0
  49. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/cancellation.py +0 -0
  50. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/clock.py +0 -0
  51. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/guard.py +0 -0
  52. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/meta.py +0 -0
  53. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/runner.py +0 -0
  54. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/subgraph_locks.py +0 -0
  55. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/sugar.py +0 -0
  56. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/timer.py +0 -0
  57. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/core/versioning.py +0 -0
  58. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/__init__.py +0 -0
  59. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/adapters.py +0 -0
  60. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/backoff.py +0 -0
  61. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/backpressure.py +0 -0
  62. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/cascading_cache.py +0 -0
  63. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/checkpoint.py +0 -0
  64. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/composite.py +0 -0
  65. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/cron.py +0 -0
  66. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/data_structures.py +0 -0
  67. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/resilience.py +0 -0
  68. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/sources.py +0 -0
  69. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/tier1.py +0 -0
  70. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/extra/tier2.py +0 -0
  71. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/graph/__init__.py +0 -0
  72. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/graph/graph.py +0 -0
  73. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/integrations/__init__.py +0 -0
  74. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/integrations/django.py +0 -0
  75. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/integrations/fastapi.py +0 -0
  76. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/ai.py +0 -0
  77. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/cqrs.py +0 -0
  78. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/memory.py +0 -0
  79. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/messaging.py +0 -0
  80. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/orchestration.py +0 -0
  81. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/reactive_layout/__init__.py +0 -0
  82. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/reactive_layout/measurement_adapters.py +0 -0
  83. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/reactive_layout/reactive_block_layout.py +0 -0
  84. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/patterns/reactive_layout/reactive_layout.py +0 -0
  85. {graphrefly-0.8.0 → graphrefly-0.9.0}/src/graphrefly/py.typed +0 -0
  86. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/bench_core.py +0 -0
  87. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/conftest.py +0 -0
  88. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_adapter_contract.py +0 -0
  89. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_adapters_ingest.py +0 -0
  90. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_adapters_storage.py +0 -0
  91. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_backpressure.py +0 -0
  92. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_cascading_cache.py +0 -0
  93. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_concurrency.py +0 -0
  94. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_core.py +0 -0
  95. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_django.py +0 -0
  96. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_dynamic_node.py +0 -0
  97. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_edge_cases.py +0 -0
  98. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_composite.py +0 -0
  99. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_data_structures.py +0 -0
  100. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_resilience.py +0 -0
  101. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_sources.py +0 -0
  102. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_sources_http.py +0 -0
  103. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_tier1.py +0 -0
  104. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_extra_tier2.py +0 -0
  105. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_fastapi.py +0 -0
  106. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_graph.py +0 -0
  107. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_guard.py +0 -0
  108. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_measurement_adapters.py +0 -0
  109. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_patterns_ai.py +0 -0
  110. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_patterns_cqrs.py +0 -0
  111. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_patterns_memory.py +0 -0
  112. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_patterns_messaging.py +0 -0
  113. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_patterns_orchestration.py +0 -0
  114. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_patterns_reduction.py +0 -0
  115. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_perf_smoke.py +0 -0
  116. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_protocol.py +0 -0
  117. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_reactive_block_layout.py +0 -0
  118. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_reactive_layout.py +0 -0
  119. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_reduction.py +0 -0
  120. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_regressions.py +0 -0
  121. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_runner.py +0 -0
  122. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_smoke.py +0 -0
  123. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_sugar.py +0 -0
  124. {graphrefly-0.8.0 → graphrefly-0.9.0}/tests/test_versioning.py +0 -0
  125. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/.gitignore +0 -0
  126. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/README.md +0 -0
  127. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/astro.config.mjs +0 -0
  128. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/content.config.ts +0 -0
  129. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/package.json +0 -0
  130. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/pnpm-lock.yaml +0 -0
  131. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/public/llms.txt +0 -0
  132. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/py-api-sidebar.mjs +0 -0
  133. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/scripts/gen_api_docs.py +0 -0
  134. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/scripts/sync-docs.mjs +0 -0
  135. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/components/GraphreflyHero.astro +0 -0
  136. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/components/Header.astro +0 -0
  137. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/components/MobileMenuFooter.astro +0 -0
  138. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/components/PyodidePlayground.tsx +0 -0
  139. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/components/Sidebar.astro +0 -0
  140. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/components/SiteTitle.astro +0 -0
  141. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/BackoffPreset.md +0 -0
  142. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/BackoffStrategy.md +0 -0
  143. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/CheckpointAdapter.md +0 -0
  144. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/CircuitBreaker.md +0 -0
  145. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/CircuitOpenError.md +0 -0
  146. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/DeferWhen.md +0 -0
  147. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/DictCheckpointAdapter.md +0 -0
  148. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/DistillBundle.md +0 -0
  149. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/EmitStrategy.md +0 -0
  150. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/Extraction.md +0 -0
  151. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/FileCheckpointAdapter.md +0 -0
  152. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/HttpBundle.md +0 -0
  153. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/JitterMode.md +0 -0
  154. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/MemoryCheckpointAdapter.md +0 -0
  155. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/Message.md +0 -0
  156. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/MessageType.md +0 -0
  157. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/Messages.md +0 -0
  158. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/NodeActions.md +0 -0
  159. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/NodeFn.md +0 -0
  160. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/NodeImpl.md +0 -0
  161. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/NodeStatus.md +0 -0
  162. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/PipeOperator.md +0 -0
  163. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/PubSubHub.md +0 -0
  164. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/ReactiveIndexBundle.md +0 -0
  165. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/ReactiveListBundle.md +0 -0
  166. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/ReactiveLogBundle.md +0 -0
  167. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/ReactiveMapBundle.md +0 -0
  168. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/SqliteCheckpointAdapter.md +0 -0
  169. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/SubscribeHints.md +0 -0
  170. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/TokenBucket.md +0 -0
  171. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/VerifiableBundle.md +0 -0
  172. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/Versioned.md +0 -0
  173. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/WithBreakerBundle.md +0 -0
  174. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/WithStatusBundle.md +0 -0
  175. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/audit.md +0 -0
  176. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/batch.md +0 -0
  177. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/buffer.md +0 -0
  178. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/buffer_count.md +0 -0
  179. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/buffer_time.md +0 -0
  180. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/cached.md +0 -0
  181. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/checkpoint_node_value.md +0 -0
  182. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/circuit_breaker.md +0 -0
  183. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/combine.md +0 -0
  184. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/concat.md +0 -0
  185. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/concat_map.md +0 -0
  186. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/constant.md +0 -0
  187. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/debounce.md +0 -0
  188. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/decorrelated_jitter.md +0 -0
  189. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/delay.md +0 -0
  190. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/derived.md +0 -0
  191. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/dispatch_messages.md +0 -0
  192. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/distill.md +0 -0
  193. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/distinct_until_changed.md +0 -0
  194. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/effect.md +0 -0
  195. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/element_at.md +0 -0
  196. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/emit_with_batch.md +0 -0
  197. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/empty.md +0 -0
  198. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/exhaust_map.md +0 -0
  199. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/exponential.md +0 -0
  200. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/fibonacci.md +0 -0
  201. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/filter.md +0 -0
  202. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/find.md +0 -0
  203. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/first.md +0 -0
  204. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/first_value_from.md +0 -0
  205. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/flat_map.md +0 -0
  206. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/for_each.md +0 -0
  207. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_any.md +0 -0
  208. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_async_iter.md +0 -0
  209. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_awaitable.md +0 -0
  210. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_cron.md +0 -0
  211. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_event_emitter.md +0 -0
  212. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_fs_watch.md +0 -0
  213. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_git_hook.md +0 -0
  214. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_http.md +0 -0
  215. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_iter.md +0 -0
  216. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_mcp.md +0 -0
  217. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_timer.md +0 -0
  218. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_webhook.md +0 -0
  219. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/from_websocket.md +0 -0
  220. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/gate.md +0 -0
  221. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/index.md +0 -0
  222. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/interval.md +0 -0
  223. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/is_batching.md +0 -0
  224. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/is_phase2_message.md +0 -0
  225. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/is_terminal_message.md +0 -0
  226. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/last.md +0 -0
  227. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/linear.md +0 -0
  228. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/log_slice.md +0 -0
  229. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/map.md +0 -0
  230. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/merge.md +0 -0
  231. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/message_tier.md +0 -0
  232. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/never.md +0 -0
  233. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/node.md +0 -0
  234. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/of.md +0 -0
  235. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/operator.md +0 -0
  236. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/pairwise.md +0 -0
  237. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/partition_for_batch.md +0 -0
  238. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/pausable.md +0 -0
  239. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/pipe.md +0 -0
  240. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/producer.md +0 -0
  241. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/propagates_to_meta.md +0 -0
  242. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/pubsub.md +0 -0
  243. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/race.md +0 -0
  244. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/rate_limiter.md +0 -0
  245. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/reactive_index.md +0 -0
  246. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/reactive_list.md +0 -0
  247. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/reactive_log.md +0 -0
  248. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/reactive_map.md +0 -0
  249. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/reduce.md +0 -0
  250. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/repeat.md +0 -0
  251. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/replay.md +0 -0
  252. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/rescue.md +0 -0
  253. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/resolve_backoff_preset.md +0 -0
  254. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/restore_graph_checkpoint.md +0 -0
  255. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/retry.md +0 -0
  256. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/sample.md +0 -0
  257. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/save_graph_checkpoint.md +0 -0
  258. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/scan.md +0 -0
  259. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/share.md +0 -0
  260. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/skip.md +0 -0
  261. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/start_with.md +0 -0
  262. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/state.md +0 -0
  263. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/subscribe.md +0 -0
  264. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/switch_map.md +0 -0
  265. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/take.md +0 -0
  266. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/take_until.md +0 -0
  267. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/take_while.md +0 -0
  268. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/tap.md +0 -0
  269. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/throttle.md +0 -0
  270. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/throw_error.md +0 -0
  271. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/timeout.md +0 -0
  272. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/to_array.md +0 -0
  273. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/to_list.md +0 -0
  274. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/to_sse.md +0 -0
  275. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/to_websocket.md +0 -0
  276. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/token_bucket.md +0 -0
  277. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/token_tracker.md +0 -0
  278. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/verifiable.md +0 -0
  279. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/window.md +0 -0
  280. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/window_count.md +0 -0
  281. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/window_time.md +0 -0
  282. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/with_breaker.md +0 -0
  283. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/with_latest_from.md +0 -0
  284. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/with_max_attempts.md +0 -0
  285. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/with_status.md +0 -0
  286. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/api/zip.md +0 -0
  287. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/index.mdx +0 -0
  288. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content/docs/lab/python.mdx +0 -0
  289. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/content.config.ts +0 -0
  290. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/env.d.ts +0 -0
  291. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/src/styles/custom.css +0 -0
  292. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/theme-prototypes.html +0 -0
  293. {graphrefly-0.8.0 → graphrefly-0.9.0}/website/tsconfig.json +0 -0
@@ -2,6 +2,14 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v0.9.0 (2026-04-06)
6
+
7
+ ### Features
8
+
9
+ - 8.3
10
+ ([`39b0a9e`](https://github.com/graphrefly/graphrefly-py/commit/39b0a9e8e2a034a27352b2ea054182d58065903f))
11
+
12
+
5
13
  ## v0.8.0 (2026-04-06)
6
14
 
7
15
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graphrefly
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Reactive graph protocol for human + LLM co-operation. Composable nodes, glitch-free diamond resolution, two-phase push, durable streaming. Zero dependencies.
5
5
  Project-URL: Homepage, https://py.graphrefly.dev
6
6
  Project-URL: Repository, https://github.com/graphrefly/graphrefly-py
@@ -139,6 +139,9 @@ Union-find over node identity merges components when nodes list dependencies at
139
139
  - **~~`to_json()` → `to_dict()` + `to_json_string()` (Phase 1.4, noted 2026-04-05, resolved 2026-04-05):~~** PY: `to_json()` renamed to `to_json_string()`; `to_dict()` added as alias of `snapshot()`; `to_json` alias removed (pre-1.0, no backward compat needed). TS: `toJSON()` renamed to `toObject()`; `toJSON()` kept as ECMAScript hook. Spec §3.8 updated.
140
140
  - **~~Initial value, cached state, and equals interaction (all phases, noted 2026-04-05, resolved 2026-04-05):~~** Resolved with `_SENTINEL` / `NO_VALUE` sentinel (TS: `Symbol.for("graphrefly/NO_VALUE")`, PY: `_SENTINEL = object()`). Replaces the `_has_emitted_data` boolean flag entirely. One field (`_cached`) instead of two — impossible to desync. Key semantics: (1) When `initial` option is present (even as `None`), `_cached = initial` — `equals` IS called on first emission. (2) When `initial` is absent, `_cached = _SENTINEL` — first emission always DATA. (3) INVALIDATE / `reset_on_teardown` set `_cached = _SENTINEL`. (4) Resubscribable: terminal reset now also sets `_cached = _SENTINEL` — new subscriber always gets DATA. (5) Reconnect: cache retained → same-value emits RESOLVED — correct. (6) `get()` returns `None` when `_cached is _SENTINEL`. Spec §2.5 updated.
141
141
  - **Auto-edge registration is local-only (Phase 1.1, noted 2026-04-05):** `Graph.add()` auto-registers edges for deps within the same `Graph` instance only. Cross-subgraph deps still require explicit `connect()`. Consistent with spec: cross-subgraph edges are explicit wiring.
142
+ - **GraphSpec cross-language parity (Phase 8.3, noted 2026-04-06, QA 2026-04-06):** Both TS and PY implement `compileSpec`/`compile_spec`, `decompileGraph`/`decompile_graph`, `llmCompose`/`llm_compose`, `llmRefine`/`llm_refine`, `specDiff`/`spec_diff`, and `validateSpec`/`validate_spec` in `patterns/graphspec`. Key alignment: (1) `GraphSpec` schema is identical JSON shape — `nodes`, `templates`, `feedback` top-level keys. TS uses TypeScript types; PY uses TypedDict. (2) `compile_spec` resolves nodes in dependency order (state/producer first, then derived/effect/operator). Catalog is passed explicitly (`GraphSpecCatalog`) — no global registry. (3) Template instantiation creates mounted subgraphs via `graph.mount()`. `$param` bindings resolve to top-level nodes. (4) Feedback edges wire via §8.1 `feedback()` primitive. (5) `decompile_graph` uses `describe(detail="standard")`, skips `__meta__` and `__feedback_*` internal nodes. Template detection via meta-based recovery (primary) + structural fingerprinting (fallback; includes dep names for accuracy). (6) `spec_diff` is pure JSON comparison — template-aware, feedback-aware. (7) LLM APIs (`llm_compose`/`llm_refine`) share identical system prompt and validation pipeline. (8) `validate_spec` checks bind targets exist in outer nodes, rejects feedback self-cycles, validates template param completeness. QA fixes: idempotent unsub in feedback(), deterministic output node selection in decompile, `contextlib.suppress` for connect dedup. Both repos: 35 tests each.
143
+ - **Feedback bare DATA to reentry/counter — deferred to 8.2 (Phase 8.1, noted 2026-04-06, decided 2026-04-06):** Both TS and PY `feedback()` send bare `[DATA]` to `reentry` and `counter` nodes without a preceding `DIRTY`. This is a deliberate protocol shortcut: the feedback subscriber operates outside the normal two-phase push because it is a subscribe-based bridge (not a node). Acceptable because feedback reentry targets are always state nodes (which re-derive DIRTY internally via `down()`). Will be resolved when feedback is rearchitected as a graph-visible bridge node in 8.2 — at that point the bridge node participates in two-phase push naturally.
144
+ - **`llm_compose`/`llm_refine` sync (PY) vs async (TS) — intentional divergence (Phase 8.3, noted 2026-04-06):** PY: synchronous, adapter must return `LLMResponse` directly. TS: `async function` returning `Promise<GraphSpec>`. PY design invariant: no `async def` / `Awaitable` in public APIs. TS spec §5.10 allows `await` at system boundaries (LLM adapter is external I/O, not reactive scheduling). Both are correct for their language idiom. Adapter contracts differ: PY adapters must be sync; TS adapters return Promise-compatible values.
142
145
  - **Reduction primitives cross-language parity (Phase 8.1, noted 2026-04-06, QA 2026-04-06):** Both TS and PY implement `stratify`, `funnel`, `feedback`, `budget_gate`/`budgetGate`, and `scorer` in `patterns/reduction`. All five follow the orchestration factory pattern (`_base_meta`, `_register_step`). Key alignment: (1) `stratify` buffers DIRTY until DATA arrives — on classifier miss, emits `[DIRTY, RESOLVED]` to preserve spec §1.3.1 (both). (2) `funnel` bridges stages via `subscribe` forwarding DIRTY/DATA/RESOLVED/COMPLETE/ERROR to preserve two-phase protocol. TODO(8.2): replace with graph-visible bridge nodes. (3) `feedback` counter node is source of truth (resettable via `graph.set()`); uses `continue` (not `return`) on max_iterations so remaining batch messages process. Counter name is `__feedback_<condition>` to support multiple loops per graph. (4) `budget_gate`/`budgetGate` force-flushes all buffered items on terminal regardless of budget; sends RESUME before terminal if paused; forwards constraint ERROR downstream, silences constraint COMPLETE, forwards unknown constraint types via default. (5) `scorer` coerces `None`/`undefined` to 0 before multiplication (no TypeError/NaN divergence). TS `ScoredItem` is a plain object; PY `ScoredItem` is a class with `__slots__` and `__eq__`. Meta keys: `reduction: True`, `reduction_type: "<name>"`. Both repos: 22 tests each.
143
146
 
144
147
  ---
@@ -501,15 +501,19 @@ Pre-wired graphs for common "info → action" domains. Users fork/extend.
501
501
  - [ ] `issue_tracker_graph(opts)` → Graph — findings → extraction → verifiable assertions → regression detection → distillation → prioritized queue
502
502
  - [ ] `content_moderation_graph(opts)` → Graph — ingest → LLM classification → human review → feedback → policy refinement
503
503
  - [ ] `data_quality_graph(opts)` → Graph — DB/API ingest → schema validation → anomaly detection → drift alerting → remediation suggestions
504
+ - [ ] Rearchitect `feedback()` as graph-visible bridge node (replaces subscribe-based shortcut; enables proper DIRTY→DATA two-phase on reentry/counter; resolves bare-DATA protocol gap)
505
+ - [ ] Rearchitect `funnel()` bridges as graph-visible nodes (replaces subscribe forwarding; resolves §5.9 imperative trigger violation + teardown leak)
506
+ - [ ] `stratify` two-dep gating: gate classification on both source and rules settling (eliminates stale-rules race when both updated in same `batch()`)
504
507
 
505
508
  ### 8.3 — LLM graph composition
506
509
 
507
- - [ ] `GraphSpec` schema — JSON schema for declarative graph topology. Serializable, diffable.
508
- - [ ] `compile_spec(spec)` → Graph — instantiate from spec
509
- - [ ] `decompile_graph(graph)` → GraphSpec — extract spec from running graph
510
- - [ ] `llm_compose(problem, adapter, opts)` → GraphSpec — LLM generates topology from natural language
511
- - [ ] `llm_refine(graph, feedback, adapter)` → GraphSpec — LLM modifies existing topology
512
- - [ ] `spec_diff(spec_a, spec_b)` — structural diff between specs
510
+ - [x] `GraphSpec` schema — JSON schema for declarative graph topology. Serializable, diffable.
511
+ - [x] `compile_spec(spec, catalog)` → Graph — instantiate from spec (dep-order resolution, templates via `mount()`, feedback via §8.1)
512
+ - [x] `decompile_graph(graph)` → GraphSpec — extract spec from running graph (meta-based + structural fingerprint template detection)
513
+ - [x] `llm_compose(problem, adapter, opts)` → GraphSpec — LLM generates topology from natural language
514
+ - [x] `llm_refine(spec, feedback, adapter)` → GraphSpec — LLM modifies existing topology
515
+ - [x] `spec_diff(spec_a, spec_b)` — structural diff between specs (template-aware, feedback-aware)
516
+ - [x] `validate_spec(spec)` → GraphSpecValidation — structural validation (types, deps, templates, feedback, bind targets)
513
517
 
514
518
  ### 8.4 — Audit & accountability
515
519
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "graphrefly"
3
- version = "0.8.0"
3
+ version = "0.9.0"
4
4
  description = "Reactive graph protocol for human + LLM co-operation. Composable nodes, glitch-free diamond resolution, two-phase push, durable streaming. Zero dependencies."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -19,7 +19,13 @@ if TYPE_CHECKING:
19
19
  from graphrefly.core.guard import MutationRecord
20
20
 
21
21
  from graphrefly.core.node import _SENTINEL
22
- from graphrefly.core.protocol import Messages, MessageType, emit_with_batch, propagates_to_meta
22
+ from graphrefly.core.protocol import (
23
+ Messages,
24
+ MessageType,
25
+ emit_with_batch,
26
+ message_tier,
27
+ propagates_to_meta,
28
+ )
23
29
 
24
30
  # ---------------------------------------------------------------------------
25
31
  # Public types
@@ -506,9 +512,7 @@ class DynamicNodeImpl[T]:
506
512
 
507
513
  # singleDep DIRTY skip optimization
508
514
  if self._can_skip_dirty():
509
- has_phase2 = any(
510
- m[0] is MessageType.DATA or m[0] is MessageType.RESOLVED for m in messages
511
- )
515
+ has_phase2 = any(message_tier(m[0]) == 2 for m in messages)
512
516
  if has_phase2:
513
517
  filtered = [m for m in messages if m[0] is not MessageType.DIRTY]
514
518
  if filtered:
@@ -18,7 +18,13 @@ from graphrefly.core.guard import (
18
18
  normalize_actor,
19
19
  record_mutation,
20
20
  )
21
- from graphrefly.core.protocol import Messages, MessageType, emit_with_batch, propagates_to_meta
21
+ from graphrefly.core.protocol import (
22
+ Messages,
23
+ MessageType,
24
+ emit_with_batch,
25
+ message_tier,
26
+ propagates_to_meta,
27
+ )
22
28
  from graphrefly.core.subgraph_locks import (
23
29
  acquire_subgraph_write_lock_with_defer,
24
30
  ensure_registered,
@@ -824,12 +830,7 @@ class NodeImpl[T]:
824
830
  sink_messages = terminal_passthrough
825
831
  self._handle_local_lifecycle(lifecycle_messages)
826
832
  if self._can_skip_dirty():
827
- has_phase2 = False
828
- for m in sink_messages:
829
- t = m[0]
830
- if t is MessageType.DATA or t is MessageType.RESOLVED:
831
- has_phase2 = True
832
- break
833
+ has_phase2 = any(message_tier(m[0]) == 2 for m in sink_messages)
833
834
  if has_phase2:
834
835
  filtered = [m for m in sink_messages if m[0] is not MessageType.DIRTY]
835
836
  if filtered:
@@ -359,7 +359,7 @@ def _emit_partition(
359
359
  # skip partition_for_batch allocation entirely.
360
360
  if len(messages) == 1:
361
361
  t = messages[0][0]
362
- if t is MessageType.DATA or t is MessageType.RESOLVED:
362
+ if message_tier(t) == 2:
363
363
  if _should_defer_phase2(bs, defer_when):
364
364
 
365
365
  def _emit_single() -> None:
@@ -3,6 +3,7 @@
3
3
  from graphrefly.patterns import (
4
4
  ai,
5
5
  cqrs,
6
+ graphspec,
6
7
  memory,
7
8
  messaging,
8
9
  orchestration,
@@ -10,4 +11,13 @@ from graphrefly.patterns import (
10
11
  reduction,
11
12
  )
12
13
 
13
- __all__ = ["ai", "cqrs", "memory", "messaging", "orchestration", "reactive_layout", "reduction"]
14
+ __all__ = [
15
+ "ai",
16
+ "cqrs",
17
+ "graphspec",
18
+ "memory",
19
+ "messaging",
20
+ "orchestration",
21
+ "reactive_layout",
22
+ "reduction",
23
+ ]