igniter 0.5.0 → 0.5.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -3
- data/README.md +150 -658
- data/docs/README.md +59 -0
- data/docs/assets/README.md +8 -0
- data/docs/concepts/README.md +18 -0
- data/docs/concepts/igniter.md +119 -0
- data/docs/dev/README.md +48 -0
- data/docs/dev/agent-orchestra-dna.md +271 -0
- data/docs/dev/ai-agents-target-plan.md +178 -0
- data/docs/dev/application-target-plan.md +45 -0
- data/docs/dev/application-web-integration.md +59 -0
- data/docs/dev/application-web-poc-pattern-guide.md +167 -0
- data/docs/dev/architect-supervisor-bootstrap.md +322 -0
- data/docs/dev/architecture.md +20 -0
- data/docs/dev/cluster-target-plan.md +43 -0
- data/docs/dev/contract-persistence-target-plan.md +426 -0
- data/docs/dev/current-runtime-snapshot.md +73 -0
- data/docs/dev/data-ownership.md +29 -0
- data/docs/dev/document-rotation.md +51 -0
- data/docs/dev/embed-target-plan.md +51 -0
- data/docs/dev/igniter-web-dsl-sketch.md +151 -0
- data/docs/dev/igniter-web-target-plan.md +56 -0
- data/docs/dev/mcp-adapter-package-spec.md +81 -0
- data/docs/dev/module-system.md +46 -0
- data/docs/dev/package-map.md +112 -0
- data/docs/guide/README.md +77 -0
- data/docs/guide/ai-and-tools.md +33 -0
- data/docs/guide/api-and-runtime.md +38 -0
- data/docs/guide/app.md +45 -0
- data/docs/guide/application-capsules.md +139 -0
- data/docs/guide/application-showcase-portfolio.md +181 -0
- data/docs/guide/cli.md +70 -0
- data/docs/guide/cluster.md +55 -0
- data/docs/guide/configuration.md +31 -0
- data/docs/guide/contract-class-dsl.md +154 -0
- data/docs/guide/core-runtime-features.md +34 -0
- data/docs/guide/core.md +43 -0
- data/docs/guide/credentials.md +51 -0
- data/docs/guide/deployment-modes.md +63 -0
- data/docs/guide/distributed-workflows.md +21 -0
- data/docs/guide/getting-started.md +49 -0
- data/docs/guide/how-tos.md +33 -0
- data/docs/guide/igniter-lang-foundation.md +133 -0
- data/docs/guide/integrations.md +47 -0
- data/docs/guide/interactive-app-structure.md +91 -0
- data/docs/guide/store-adapters.md +183 -0
- data/docs/research/README.md +131 -0
- data/docs/research/contract-persistence-landing-zone.md +126 -0
- data/docs/research/contract-persistence-organic-model.md +279 -0
- data/docs/research/contract-persistence-organic-model.ru.md +277 -0
- data/docs/research/horizon-protocol.md +180 -0
- data/docs/research/igniter-lang-convergence-report.md +338 -0
- data/docs/research/project-status-horizon-report.md +363 -0
- data/docs/research/vision-handoff-protocol.md +141 -0
- data/docs/research/wizard-type-spec-architecture.md +293 -0
- data/docs/research/wizard-type-spec-research-request.md +134 -0
- data/docs/store/README.md +7 -0
- data/docs/store/convergence-audit.md +901 -0
- data/examples/README.md +152 -344
- data/examples/catalog.rb +1486 -0
- data/examples/cluster/incident_workflow.rb +70 -0
- data/examples/cluster/incidents.rb +63 -0
- data/examples/cluster/mesh_diagnostics.rb +89 -0
- data/examples/cluster/remediation.rb +63 -0
- data/examples/cluster/routing.rb +65 -0
- data/examples/contracts/aggregates.rb +39 -0
- data/examples/contracts/auditing.rb +35 -0
- data/examples/contracts/basic_pricing.rb +31 -0
- data/examples/contracts/branching.rb +36 -0
- data/examples/contracts/build_effect_executor_pack.rb +88 -0
- data/examples/contracts/build_your_own_pack.rb +82 -0
- data/examples/contracts/capabilities.rb +34 -0
- data/examples/contracts/class_callable.rb +45 -0
- data/examples/contracts/class_pricing.rb +32 -0
- data/examples/contracts/collection.rb +44 -0
- data/examples/contracts/commerce.rb +44 -0
- data/examples/contracts/compose_your_own_packs.rb +110 -0
- data/examples/contracts/composition.rb +61 -0
- data/examples/contracts/content_addressing.rb +33 -0
- data/examples/contracts/contractable_service.rb +43 -0
- data/examples/contracts/contractable_shadow.rb +69 -0
- data/examples/contracts/create_pack.rb +105 -0
- data/examples/contracts/dataflow.rb +57 -0
- data/examples/contracts/debug.rb +32 -0
- data/examples/contracts/debug_pack_authoring.rb +31 -0
- data/examples/contracts/diagnostics.rb +33 -0
- data/examples/contracts/differential.rb +97 -0
- data/examples/contracts/effects.rb +34 -0
- data/examples/contracts/embed_class_registration.rb +40 -0
- data/examples/contracts/embed_human_sugar.rb +106 -0
- data/examples/contracts/formula.rb +32 -0
- data/examples/contracts/incremental.rb +44 -0
- data/examples/contracts/introspection.rb +48 -0
- data/examples/contracts/invariants.rb +54 -0
- data/examples/contracts/journal.rb +37 -0
- data/examples/contracts/lang_foundation.rb +37 -0
- data/examples/contracts/mcp.rb +62 -0
- data/examples/contracts/mcp_host.rb +55 -0
- data/examples/contracts/mcp_server.rb +25 -0
- data/examples/contracts/piecewise.rb +30 -0
- data/examples/contracts/provenance.rb +55 -0
- data/examples/contracts/reactive.rb +62 -0
- data/examples/contracts/saga.rb +56 -0
- data/examples/contracts/scale.rb +30 -0
- data/examples/contracts/step_result.rb +58 -0
- data/examples/run.rb +163 -0
- data/lib/igniter/cluster.rb +3 -0
- data/lib/igniter/contract.rb +1 -326
- data/lib/igniter/monorepo_packages.rb +16 -0
- data/lib/igniter/version.rb +1 -1
- data/lib/igniter/web.rb +3 -0
- data/lib/igniter.rb +51 -43
- data/packages/igniter-agents/README.md +44 -0
- data/packages/igniter-agents/lib/igniter/agents/agent_definition.rb +26 -0
- data/packages/igniter-agents/lib/igniter/agents/agent_run.rb +47 -0
- data/packages/igniter-agents/lib/igniter/agents/agent_turn.rb +34 -0
- data/packages/igniter-agents/lib/igniter/agents/runner.rb +56 -0
- data/packages/igniter-agents/lib/igniter/agents/tool_call.rb +26 -0
- data/packages/igniter-agents/lib/igniter/agents/trace_event.rb +24 -0
- data/packages/igniter-agents/lib/igniter/agents.rb +33 -0
- data/packages/igniter-agents/lib/igniter-agents.rb +3 -0
- data/packages/igniter-ai/README.md +42 -0
- data/packages/igniter-ai/lib/igniter/ai/client.rb +18 -0
- data/packages/igniter-ai/lib/igniter/ai/error.rb +14 -0
- data/packages/igniter-ai/lib/igniter/ai/model_request.rb +28 -0
- data/packages/igniter-ai/lib/igniter/ai/model_response.rb +31 -0
- data/packages/igniter-ai/lib/igniter/ai/providers/fake.rb +24 -0
- data/packages/igniter-ai/lib/igniter/ai/providers/openai_responses.rb +100 -0
- data/packages/igniter-ai/lib/igniter/ai/providers/recorded.rb +40 -0
- data/packages/igniter-ai/lib/igniter/ai/usage.rb +32 -0
- data/packages/igniter-ai/lib/igniter/ai.rb +28 -0
- data/packages/igniter-ai/lib/igniter-ai.rb +3 -0
- data/packages/igniter-application/README.md +194 -0
- data/packages/igniter-application/lib/igniter/application/agent_definition.rb +38 -0
- data/packages/igniter-application/lib/igniter/application/agent_registry.rb +33 -0
- data/packages/igniter-application/lib/igniter/application/agent_runtime.rb +29 -0
- data/packages/igniter-application/lib/igniter/application/agents_builder.rb +26 -0
- data/packages/igniter-application/lib/igniter/application/ai_builder.rb +26 -0
- data/packages/igniter-application/lib/igniter/application/ai_provider_definition.rb +59 -0
- data/packages/igniter-application/lib/igniter/application/ai_registry.rb +34 -0
- data/packages/igniter-application/lib/igniter/application/application_assembly_plan.rb +67 -0
- data/packages/igniter-application/lib/igniter/application/application_blueprint.rb +227 -0
- data/packages/igniter-application/lib/igniter/application/application_capsule_report.rb +61 -0
- data/packages/igniter-application/lib/igniter/application/application_composition_report.rb +161 -0
- data/packages/igniter-application/lib/igniter/application/application_handoff_manifest.rb +100 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_commit_readiness.rb +182 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_dry_run_result.rb +190 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_ledger_commit.rb +285 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_ledger_verification.rb +301 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_operation_digest.rb +68 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_plan.rb +200 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_plan_verification.rb +140 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_readiness.rb +226 -0
- data/packages/igniter-application/lib/igniter/application/application_host_activation_receipt.rb +151 -0
- data/packages/igniter-application/lib/igniter/application/application_layout.rb +91 -0
- data/packages/igniter-application/lib/igniter/application/application_load_path.rb +38 -0
- data/packages/igniter-application/lib/igniter/application/application_load_report.rb +74 -0
- data/packages/igniter-application/lib/igniter/application/application_manifest.rb +65 -0
- data/packages/igniter-application/lib/igniter/application/application_structure_entry.rb +58 -0
- data/packages/igniter-application/lib/igniter/application/application_structure_plan.rb +128 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_applied_verification.rb +301 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_apply_plan.rb +167 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_apply_result.rb +321 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_bundle_artifact.rb +160 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_bundle_plan.rb +125 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_bundle_verification.rb +154 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_intake_plan.rb +195 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_inventory.rb +153 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_readiness.rb +260 -0
- data/packages/igniter-application/lib/igniter/application/application_transfer_receipt.rb +179 -0
- data/packages/igniter-application/lib/igniter/application/artifact_reference.rb +39 -0
- data/packages/igniter-application/lib/igniter/application/boot_phase.rb +27 -0
- data/packages/igniter-application/lib/igniter/application/boot_plan.rb +55 -0
- data/packages/igniter-application/lib/igniter/application/boot_report.rb +70 -0
- data/packages/igniter-application/lib/igniter/application/capsule_builder.rb +396 -0
- data/packages/igniter-application/lib/igniter/application/capsule_export.rb +26 -0
- data/packages/igniter-application/lib/igniter/application/capsule_import.rb +38 -0
- data/packages/igniter-application/lib/igniter/application/collection_invoker.rb +54 -0
- data/packages/igniter-application/lib/igniter/application/collection_transport_adapter.rb +37 -0
- data/packages/igniter-application/lib/igniter/application/compose_invoker.rb +51 -0
- data/packages/igniter-application/lib/igniter/application/compose_transport_adapter.rb +34 -0
- data/packages/igniter-application/lib/igniter/application/config.rb +86 -0
- data/packages/igniter-application/lib/igniter/application/config_builder.rb +69 -0
- data/packages/igniter-application/lib/igniter/application/contract_registry.rb +30 -0
- data/packages/igniter-application/lib/igniter/application/credential_definition.rb +65 -0
- data/packages/igniter-application/lib/igniter/application/credential_store.rb +68 -0
- data/packages/igniter-application/lib/igniter/application/embedded_host.rb +23 -0
- data/packages/igniter-application/lib/igniter/application/environment.rb +1071 -0
- data/packages/igniter-application/lib/igniter/application/feature_slice.rb +61 -0
- data/packages/igniter-application/lib/igniter/application/feature_slice_report.rb +43 -0
- data/packages/igniter-application/lib/igniter/application/file_backed_host_activation_ledger_adapter.rb +138 -0
- data/packages/igniter-application/lib/igniter/application/file_backed_installed_capsule_registry.rb +132 -0
- data/packages/igniter-application/lib/igniter/application/flow_declaration.rb +62 -0
- data/packages/igniter-application/lib/igniter/application/flow_event.rb +50 -0
- data/packages/igniter-application/lib/igniter/application/flow_session_snapshot.rb +98 -0
- data/packages/igniter-application/lib/igniter/application/installed_capsule_entry.rb +47 -0
- data/packages/igniter-application/lib/igniter/application/interface.rb +11 -0
- data/packages/igniter-application/lib/igniter/application/kernel.rb +385 -0
- data/packages/igniter-application/lib/igniter/application/lifecycle_plan_step.rb +38 -0
- data/packages/igniter-application/lib/igniter/application/manual_loader.rb +18 -0
- data/packages/igniter-application/lib/igniter/application/manual_scheduler.rb +15 -0
- data/packages/igniter-application/lib/igniter/application/memory_session_store.rb +33 -0
- data/packages/igniter-application/lib/igniter/application/missing_credential_error.rb +23 -0
- data/packages/igniter-application/lib/igniter/application/mount_intent.rb +48 -0
- data/packages/igniter-application/lib/igniter/application/mount_registration.rb +49 -0
- data/packages/igniter-application/lib/igniter/application/pending_action.rb +39 -0
- data/packages/igniter-application/lib/igniter/application/pending_input.rb +45 -0
- data/packages/igniter-application/lib/igniter/application/plan_executor.rb +93 -0
- data/packages/igniter-application/lib/igniter/application/profile.rb +178 -0
- data/packages/igniter-application/lib/igniter/application/provider.rb +19 -0
- data/packages/igniter-application/lib/igniter/application/provider_lifecycle_report.rb +72 -0
- data/packages/igniter-application/lib/igniter/application/provider_lifecycle_result.rb +54 -0
- data/packages/igniter-application/lib/igniter/application/provider_registration.rb +19 -0
- data/packages/igniter-application/lib/igniter/application/rack_host.rb +311 -0
- data/packages/igniter-application/lib/igniter/application/seam_lifecycle_result.rb +62 -0
- data/packages/igniter-application/lib/igniter/application/service_definition.rb +25 -0
- data/packages/igniter-application/lib/igniter/application/service_registry.rb +58 -0
- data/packages/igniter-application/lib/igniter/application/session_entry.rb +46 -0
- data/packages/igniter-application/lib/igniter/application/shutdown_plan.rb +45 -0
- data/packages/igniter-application/lib/igniter/application/shutdown_report.rb +54 -0
- data/packages/igniter-application/lib/igniter/application/snapshot.rb +35 -0
- data/packages/igniter-application/lib/igniter/application/transport_request.rb +40 -0
- data/packages/igniter-application/lib/igniter/application/transport_response.rb +22 -0
- data/packages/igniter-application/lib/igniter/application.rb +354 -0
- data/packages/igniter-application/lib/igniter-application.rb +3 -0
- data/packages/igniter-cluster/README.md +116 -0
- data/packages/igniter-cluster/lib/igniter/cluster/active_incident_set.rb +40 -0
- data/packages/igniter-cluster/lib/igniter/cluster/admission_policy.rb +158 -0
- data/packages/igniter-cluster/lib/igniter/cluster/admission_result.rb +47 -0
- data/packages/igniter-cluster/lib/igniter/cluster/capability_catalog.rb +66 -0
- data/packages/igniter-cluster/lib/igniter/cluster/capability_definition.rb +42 -0
- data/packages/igniter-cluster/lib/igniter/cluster/capability_query.rb +162 -0
- data/packages/igniter-cluster/lib/igniter/cluster/capability_router.rb +11 -0
- data/packages/igniter-cluster/lib/igniter/cluster/cluster_diagnostics_executor.rb +184 -0
- data/packages/igniter-cluster/lib/igniter/cluster/cluster_diagnostics_report.rb +49 -0
- data/packages/igniter-cluster/lib/igniter/cluster/cluster_event.rb +34 -0
- data/packages/igniter-cluster/lib/igniter/cluster/cluster_event_log.rb +27 -0
- data/packages/igniter-cluster/lib/igniter/cluster/cluster_incident.rb +42 -0
- data/packages/igniter-cluster/lib/igniter/cluster/decision_explanation.rb +31 -0
- data/packages/igniter-cluster/lib/igniter/cluster/direct_placement.rb +11 -0
- data/packages/igniter-cluster/lib/igniter/cluster/discovery_feed.rb +22 -0
- data/packages/igniter-cluster/lib/igniter/cluster/environment.rb +380 -0
- data/packages/igniter-cluster/lib/igniter/cluster/errors.rb +9 -0
- data/packages/igniter-cluster/lib/igniter/cluster/failover_plan.rb +45 -0
- data/packages/igniter-cluster/lib/igniter/cluster/failover_step.rb +32 -0
- data/packages/igniter-cluster/lib/igniter/cluster/health_policy.rb +124 -0
- data/packages/igniter-cluster/lib/igniter/cluster/incident_action.rb +49 -0
- data/packages/igniter-cluster/lib/igniter/cluster/incident_entry.rb +98 -0
- data/packages/igniter-cluster/lib/igniter/cluster/incident_executor.rb +145 -0
- data/packages/igniter-cluster/lib/igniter/cluster/incident_workflow.rb +64 -0
- data/packages/igniter-cluster/lib/igniter/cluster/kernel.rb +75 -0
- data/packages/igniter-cluster/lib/igniter/cluster/kernel_seams.rb +249 -0
- data/packages/igniter-cluster/lib/igniter/cluster/lease_grant.rb +40 -0
- data/packages/igniter-cluster/lib/igniter/cluster/lease_plan.rb +40 -0
- data/packages/igniter-cluster/lib/igniter/cluster/lease_policy.rb +96 -0
- data/packages/igniter-cluster/lib/igniter/cluster/membership_delta.rb +36 -0
- data/packages/igniter-cluster/lib/igniter/cluster/membership_feed.rb +24 -0
- data/packages/igniter-cluster/lib/igniter/cluster/membership_projection.rb +45 -0
- data/packages/igniter-cluster/lib/igniter/cluster/membership_snapshot.rb +64 -0
- data/packages/igniter-cluster/lib/igniter/cluster/memory_incident_registry.rb +169 -0
- data/packages/igniter-cluster/lib/igniter/cluster/memory_peer_registry.rb +24 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_admission.rb +24 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_admission_result.rb +40 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_execution_attempt.rb +51 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_execution_request.rb +71 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_execution_response.rb +28 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_execution_trace.rb +32 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_executor.rb +497 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_membership.rb +89 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_membership_event.rb +32 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_membership_source.rb +49 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_retry_policy.rb +42 -0
- data/packages/igniter-cluster/lib/igniter/cluster/mesh_trust_policy.rb +131 -0
- data/packages/igniter-cluster/lib/igniter/cluster/operator_timeline.rb +33 -0
- data/packages/igniter-cluster/lib/igniter/cluster/ownership_claim.rb +30 -0
- data/packages/igniter-cluster/lib/igniter/cluster/ownership_plan.rb +40 -0
- data/packages/igniter-cluster/lib/igniter/cluster/ownership_policy.rb +100 -0
- data/packages/igniter-cluster/lib/igniter/cluster/peer.rb +86 -0
- data/packages/igniter-cluster/lib/igniter/cluster/peer_discovery.rb +62 -0
- data/packages/igniter-cluster/lib/igniter/cluster/peer_health.rb +55 -0
- data/packages/igniter-cluster/lib/igniter/cluster/peer_profile.rb +102 -0
- data/packages/igniter-cluster/lib/igniter/cluster/peer_topology.rb +62 -0
- data/packages/igniter-cluster/lib/igniter/cluster/peer_view.rb +42 -0
- data/packages/igniter-cluster/lib/igniter/cluster/permissive_admission.rb +11 -0
- data/packages/igniter-cluster/lib/igniter/cluster/placement_decision.rb +38 -0
- data/packages/igniter-cluster/lib/igniter/cluster/placement_policy.rb +131 -0
- data/packages/igniter-cluster/lib/igniter/cluster/plan_action_result.rb +72 -0
- data/packages/igniter-cluster/lib/igniter/cluster/plan_execution_report.rb +57 -0
- data/packages/igniter-cluster/lib/igniter/cluster/plan_executor.rb +314 -0
- data/packages/igniter-cluster/lib/igniter/cluster/policy_admission.rb +18 -0
- data/packages/igniter-cluster/lib/igniter/cluster/policy_placement.rb +69 -0
- data/packages/igniter-cluster/lib/igniter/cluster/policy_router.rb +70 -0
- data/packages/igniter-cluster/lib/igniter/cluster/profile.rb +97 -0
- data/packages/igniter-cluster/lib/igniter/cluster/projection_executor.rb +42 -0
- data/packages/igniter-cluster/lib/igniter/cluster/projection_policy.rb +107 -0
- data/packages/igniter-cluster/lib/igniter/cluster/projection_report.rb +35 -0
- data/packages/igniter-cluster/lib/igniter/cluster/projection_stage.rb +32 -0
- data/packages/igniter-cluster/lib/igniter/cluster/rebalance_move.rb +30 -0
- data/packages/igniter-cluster/lib/igniter/cluster/rebalance_plan.rb +40 -0
- data/packages/igniter-cluster/lib/igniter/cluster/recovery_timeline.rb +33 -0
- data/packages/igniter-cluster/lib/igniter/cluster/registry_membership_source.rb +97 -0
- data/packages/igniter-cluster/lib/igniter/cluster/remediation_plan.rb +45 -0
- data/packages/igniter-cluster/lib/igniter/cluster/remediation_policy.rb +119 -0
- data/packages/igniter-cluster/lib/igniter/cluster/remediation_step.rb +44 -0
- data/packages/igniter-cluster/lib/igniter/cluster/route.rb +34 -0
- data/packages/igniter-cluster/lib/igniter/cluster/route_policy.rb +104 -0
- data/packages/igniter-cluster/lib/igniter/cluster/route_request.rb +61 -0
- data/packages/igniter-cluster/lib/igniter/cluster/topology_policy.rb +154 -0
- data/packages/igniter-cluster/lib/igniter/cluster/transport_adapter.rb +53 -0
- data/packages/igniter-cluster/lib/igniter/cluster.rb +108 -0
- data/packages/igniter-cluster/lib/igniter-cluster.rb +3 -0
- data/packages/igniter-contracts/README.md +239 -0
- data/packages/igniter-contracts/lib/igniter/contracts/api.rb +92 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/baseline_pack.rb +141 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/const_pack.rb +29 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/dsl_keyword.rb +21 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/hook_result_policies.rb +47 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/hook_spec.rb +73 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/hook_specs.rb +74 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/kernel.rb +220 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/node_type.rb +26 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/ordered_registry.rb +55 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/pack.rb +13 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/pack_manifest.rb +131 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/path_access.rb +76 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/profile.rb +133 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/project_pack.rb +42 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/registry.rb +57 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly/step_result_pack.rb +42 -0
- data/packages/igniter-contracts/lib/igniter/contracts/assembly.rb +18 -0
- data/packages/igniter-contracts/lib/igniter/contracts/contract.rb +135 -0
- data/packages/igniter-contracts/lib/igniter/contracts/contractable.rb +288 -0
- data/packages/igniter-contracts/lib/igniter/contracts/environment.rb +51 -0
- data/packages/igniter-contracts/lib/igniter/contracts/errors.rb +47 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/baseline_normalizers.rb +23 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/baseline_runtime.rb +55 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/baseline_validators.rb +113 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/builder.rb +43 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/compilation_report.rb +46 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/compiled_graph.rb +21 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/compiler.rb +66 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/const_runtime.rb +15 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/diagnostics.rb +24 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/diagnostics_report.rb +40 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/diagnostics_section.rb +37 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/effect_invocation.rb +26 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/execution_request.rb +28 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/execution_result.rb +32 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/inline_executor.rb +19 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/mutable_named_values.rb +52 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/named_values.rb +48 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/operation.rb +42 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/runtime.rb +43 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/step_result.rb +51 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/step_result_diagnostics.rb +35 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/step_result_runtime.rb +51 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/step_result_validators.rb +44 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/structured_dump.rb +49 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/validation_finding.rb +28 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution/validation_report.rb +46 -0
- data/packages/igniter-contracts/lib/igniter/contracts/execution.rb +28 -0
- data/packages/igniter-contracts/lib/igniter/contracts.rb +54 -0
- data/packages/igniter-contracts/lib/igniter/lang/backend.rb +19 -0
- data/packages/igniter-contracts/lib/igniter/lang/backends/ruby.rb +42 -0
- data/packages/igniter-contracts/lib/igniter/lang/diagnostic_payload.rb +174 -0
- data/packages/igniter-contracts/lib/igniter/lang/metadata_carrier_manifest.rb +112 -0
- data/packages/igniter-contracts/lib/igniter/lang/metadata_manifest.rb +128 -0
- data/packages/igniter-contracts/lib/igniter/lang/receipt_payload.rb +152 -0
- data/packages/igniter-contracts/lib/igniter/lang/schema_compatibility_diagnostic.rb +300 -0
- data/packages/igniter-contracts/lib/igniter/lang/types.rb +84 -0
- data/packages/igniter-contracts/lib/igniter/lang/verification_report.rb +226 -0
- data/packages/igniter-contracts/lib/igniter/lang.rb +27 -0
- data/packages/igniter-contracts/lib/igniter-contracts.rb +3 -0
- data/packages/igniter-embed/README.md +360 -0
- data/packages/igniter-embed/lib/igniter/embed/config.rb +155 -0
- data/packages/igniter-embed/lib/igniter/embed/container.rb +165 -0
- data/packages/igniter-embed/lib/igniter/embed/contract_handle.rb +23 -0
- data/packages/igniter-embed/lib/igniter/embed/contract_naming.rb +38 -0
- data/packages/igniter-embed/lib/igniter/embed/contractable/acceptance.rb +52 -0
- data/packages/igniter-embed/lib/igniter/embed/contractable/adapters.rb +33 -0
- data/packages/igniter-embed/lib/igniter/embed/contractable/config.rb +234 -0
- data/packages/igniter-embed/lib/igniter/embed/contractable/runner.rb +393 -0
- data/packages/igniter-embed/lib/igniter/embed/contractable/sugar_builder.rb +145 -0
- data/packages/igniter-embed/lib/igniter/embed/contractable.rb +29 -0
- data/packages/igniter-embed/lib/igniter/embed/contracts_builder.rb +54 -0
- data/packages/igniter-embed/lib/igniter/embed/errors.rb +14 -0
- data/packages/igniter-embed/lib/igniter/embed/execution_envelope.rb +50 -0
- data/packages/igniter-embed/lib/igniter/embed/host_builder.rb +39 -0
- data/packages/igniter-embed/lib/igniter/embed/rails.rb +21 -0
- data/packages/igniter-embed/lib/igniter/embed/registry.rb +78 -0
- data/packages/igniter-embed/lib/igniter/embed/sugar_expansion.rb +152 -0
- data/packages/igniter-embed/lib/igniter/embed.rb +38 -0
- data/packages/igniter-embed/lib/igniter-embed.rb +3 -0
- data/packages/igniter-extensions/README.md +381 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/aggregate_pack.rb +103 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/audit/builder.rb +132 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/audit/event.rb +34 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/audit/snapshot.rb +44 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/audit_pack.rb +60 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/branch_pack.rb +199 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/capabilities/declaration.rb +31 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/capabilities/error.rb +35 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/capabilities/policy.rb +20 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/capabilities/report.rb +47 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/capabilities/violation.rb +30 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/capabilities_pack.rb +146 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/collection_pack.rb +212 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/commerce_pack.rb +91 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/compose_pack.rb +213 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/content_addressing/cache.rb +59 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/content_addressing/content_key.rb +63 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/content_addressing/declaration.rb +47 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/content_addressing_pack.rb +90 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/profile.rb +196 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/report.rb +85 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/scaffold.rb +461 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/scope.rb +79 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/wizard.rb +269 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/workflow.rb +189 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/workflow_step.rb +51 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/write_result.rb +48 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/write_step.rb +63 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator/writer.rb +131 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/creator_pack.rb +128 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/aggregate_operators.rb +119 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/aggregate_state.rb +60 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/builder.rb +66 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/collection_result.rb +70 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/diff.rb +37 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/item_result.rb +44 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/result.rb +58 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/session.rb +173 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow/window_filter.rb +49 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/dataflow_pack.rb +66 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/debug/pack_audit.rb +181 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/debug/pack_snapshot.rb +46 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/debug/profile_snapshot.rb +50 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/debug/report.rb +50 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/debug_pack.rb +115 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/differential/divergence.rb +37 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/differential/formatter.rb +85 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/differential/report.rb +83 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/differential/runner.rb +136 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/differential_pack.rb +61 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/execution_report_pack.rb +38 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/incremental/formatter.rb +60 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/incremental/node_state.rb +30 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/incremental/result.rb +65 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/incremental/session.rb +146 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/incremental_pack.rb +40 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/builder.rb +27 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/cases_report.rb +47 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/error.rb +34 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/invariant.rb +30 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/report.rb +45 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/suite.rb +36 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants/violation.rb +39 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/invariants_pack.rb +88 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/journal_pack.rb +55 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/language/formula_pack.rb +185 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/language/piecewise_pack.rb +166 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/language/scale_pack.rb +147 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/lookup_pack.rb +50 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/mcp/creator_session.rb +105 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/mcp/tool_argument.rb +35 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/mcp/tool_definition.rb +33 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/mcp/tool_result.rb +28 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/mcp_pack.rb +335 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/provenance/builder.rb +80 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/provenance/lineage.rb +59 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/provenance/node_trace.rb +53 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/provenance/text_formatter.rb +62 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/provenance_pack.rb +52 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/builder.rb +43 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/dispatch_result.rb +59 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/engine.rb +79 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/event.rb +36 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/matcher.rb +20 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/plan.rb +58 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive/subscription.rb +29 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/reactive_pack.rb +169 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga/compensation.rb +25 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga/compensation_record.rb +28 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga/compensation_set.rb +47 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga/formatter.rb +39 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga/result.rb +56 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga/runner.rb +124 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts/saga_pack.rb +56 -0
- data/packages/igniter-extensions/lib/igniter/extensions/contracts.rb +445 -0
- data/packages/igniter-extensions/lib/igniter/extensions.rb +6 -0
- data/packages/igniter-extensions/lib/igniter-extensions.rb +3 -0
- data/packages/igniter-hub/README.md +25 -0
- data/packages/igniter-hub/lib/igniter/hub/catalog_entry.rb +35 -0
- data/packages/igniter-hub/lib/igniter/hub/local_catalog.rb +51 -0
- data/packages/igniter-hub/lib/igniter/hub.rb +16 -0
- data/packages/igniter-hub/lib/igniter-hub.rb +3 -0
- data/packages/igniter-mcp-adapter/README.md +65 -0
- data/packages/igniter-mcp-adapter/exe/igniter-mcp-adapter +6 -0
- data/packages/igniter-mcp-adapter/lib/igniter/mcp/adapter/host.rb +226 -0
- data/packages/igniter-mcp-adapter/lib/igniter/mcp/adapter/server.rb +148 -0
- data/packages/igniter-mcp-adapter/lib/igniter/mcp/adapter.rb +40 -0
- data/packages/igniter-mcp-adapter/lib/igniter-mcp-adapter.rb +5 -0
- data/packages/igniter-web/README.md +539 -0
- data/packages/igniter-web/lib/igniter/web/api.rb +49 -0
- data/packages/igniter-web/lib/igniter/web/application.rb +99 -0
- data/packages/igniter-web/lib/igniter/web/application_web_mount.rb +162 -0
- data/packages/igniter-web/lib/igniter/web/arbre.rb +41 -0
- data/packages/igniter-web/lib/igniter/web/component.rb +103 -0
- data/packages/igniter-web/lib/igniter/web/components/view_action_node.rb +38 -0
- data/packages/igniter-web/lib/igniter/web/components/view_ask_node.rb +52 -0
- data/packages/igniter-web/lib/igniter/web/components/view_chat_node.rb +34 -0
- data/packages/igniter-web/lib/igniter/web/components/view_compare_node.rb +41 -0
- data/packages/igniter-web/lib/igniter/web/components/view_node.rb +30 -0
- data/packages/igniter-web/lib/igniter/web/components/view_screen.rb +34 -0
- data/packages/igniter-web/lib/igniter/web/components/view_stream_node.rb +32 -0
- data/packages/igniter-web/lib/igniter/web/components/view_zone.rb +26 -0
- data/packages/igniter-web/lib/igniter/web/components.rb +10 -0
- data/packages/igniter-web/lib/igniter/web/composer.rb +84 -0
- data/packages/igniter-web/lib/igniter/web/composition_finding.rb +16 -0
- data/packages/igniter-web/lib/igniter/web/composition_policy.rb +88 -0
- data/packages/igniter-web/lib/igniter/web/composition_preset.rb +131 -0
- data/packages/igniter-web/lib/igniter/web/composition_result.rb +27 -0
- data/packages/igniter-web/lib/igniter/web/flow_interaction_adapter.rb +104 -0
- data/packages/igniter-web/lib/igniter/web/flow_surface_projection.rb +121 -0
- data/packages/igniter-web/lib/igniter/web/interaction_target.rb +50 -0
- data/packages/igniter-web/lib/igniter/web/mount_context.rb +80 -0
- data/packages/igniter-web/lib/igniter/web/page.rb +110 -0
- data/packages/igniter-web/lib/igniter/web/record.rb +54 -0
- data/packages/igniter-web/lib/igniter/web/screen_spec.rb +109 -0
- data/packages/igniter-web/lib/igniter/web/surface_manifest.rb +370 -0
- data/packages/igniter-web/lib/igniter/web/surface_structure.rb +57 -0
- data/packages/igniter-web/lib/igniter/web/view_graph.rb +25 -0
- data/packages/igniter-web/lib/igniter/web/view_graph_renderer.rb +63 -0
- data/packages/igniter-web/lib/igniter/web/view_node.rb +37 -0
- data/packages/igniter-web/lib/igniter/web.rb +107 -0
- data/packages/igniter-web/lib/igniter-web.rb +3 -0
- metadata +547 -308
- data/docs/API_V2.md +0 -537
- data/docs/APPLICATION_V1.md +0 -253
- data/docs/ARCHITECTURE_V2.md +0 -317
- data/docs/BACKLOG.md +0 -166
- data/docs/BRANCHES_V1.md +0 -213
- data/docs/CAPABILITIES_V1.md +0 -207
- data/docs/COLLECTIONS_V1.md +0 -303
- data/docs/CONSENSUS_V1.md +0 -477
- data/docs/CONTENT_ADDRESSING_V1.md +0 -221
- data/docs/DATAFLOW_V1.md +0 -274
- data/docs/DISTRIBUTED_CONTRACTS_V1.md +0 -493
- data/docs/IGNITER_CONCEPTS.md +0 -81
- data/docs/LLM_V1.md +0 -335
- data/docs/MESH_V1.md +0 -732
- data/docs/NODE_CACHE_V1.md +0 -324
- data/docs/PATTERNS.md +0 -411
- data/docs/PROACTIVE_AGENTS_V1.md +0 -293
- data/docs/SERVER_V1.md +0 -512
- data/docs/SKILLS_V1.md +0 -213
- data/docs/STORE_ADAPTERS.md +0 -154
- data/docs/TEMPORAL_V1.md +0 -174
- data/docs/TOOLS_V1.md +0 -347
- data/docs/TRANSCRIPTION_V1.md +0 -403
- data/examples/agents.rb +0 -150
- data/examples/async_store.rb +0 -47
- data/examples/basic_pricing.rb +0 -27
- data/examples/collection.rb +0 -43
- data/examples/collection_partial_failure.rb +0 -50
- data/examples/composition.rb +0 -39
- data/examples/consensus.rb +0 -239
- data/examples/dataflow.rb +0 -308
- data/examples/diagnostics.rb +0 -28
- data/examples/differential.rb +0 -161
- data/examples/distributed_server.rb +0 -94
- data/examples/distributed_workflow.rb +0 -52
- data/examples/effects.rb +0 -184
- data/examples/elocal_webhook.rb +0 -1
- data/examples/incremental.rb +0 -142
- data/examples/invariants.rb +0 -179
- data/examples/llm_tools.rb +0 -237
- data/examples/marketing_ergonomics.rb +0 -57
- data/examples/mesh.rb +0 -239
- data/examples/mesh_discovery.rb +0 -267
- data/examples/mesh_gossip.rb +0 -162
- data/examples/order_pipeline.rb +0 -163
- data/examples/provenance.rb +0 -122
- data/examples/ringcentral_routing.rb +0 -269
- data/examples/saga.rb +0 -110
- data/lib/igniter/agent/mailbox.rb +0 -96
- data/lib/igniter/agent/message.rb +0 -21
- data/lib/igniter/agent/ref.rb +0 -86
- data/lib/igniter/agent/runner.rb +0 -129
- data/lib/igniter/agent/state_holder.rb +0 -23
- data/lib/igniter/agent.rb +0 -155
- data/lib/igniter/agents/ai/alert_agent.rb +0 -111
- data/lib/igniter/agents/ai/chain_agent.rb +0 -127
- data/lib/igniter/agents/ai/critic_agent.rb +0 -163
- data/lib/igniter/agents/ai/evaluator_agent.rb +0 -193
- data/lib/igniter/agents/ai/evolution_agent.rb +0 -286
- data/lib/igniter/agents/ai/health_check_agent.rb +0 -122
- data/lib/igniter/agents/ai/observer_agent.rb +0 -184
- data/lib/igniter/agents/ai/planner_agent.rb +0 -210
- data/lib/igniter/agents/ai/router_agent.rb +0 -131
- data/lib/igniter/agents/ai/self_reflection_agent.rb +0 -175
- data/lib/igniter/agents/observability/metrics_agent.rb +0 -130
- data/lib/igniter/agents/pipeline/batch_processor_agent.rb +0 -131
- data/lib/igniter/agents/proactive_agent.rb +0 -208
- data/lib/igniter/agents/reliability/retry_agent.rb +0 -99
- data/lib/igniter/agents/scheduling/cron_agent.rb +0 -110
- data/lib/igniter/agents.rb +0 -56
- data/lib/igniter/application/app_config.rb +0 -32
- data/lib/igniter/application/autoloader.rb +0 -18
- data/lib/igniter/application/generator.rb +0 -157
- data/lib/igniter/application/scheduler.rb +0 -109
- data/lib/igniter/application/yml_loader.rb +0 -39
- data/lib/igniter/application.rb +0 -174
- data/lib/igniter/capabilities.rb +0 -68
- data/lib/igniter/compiler/compiled_graph.rb +0 -180
- data/lib/igniter/compiler/graph_compiler.rb +0 -70
- data/lib/igniter/compiler/type_resolver.rb +0 -54
- data/lib/igniter/compiler/validation_context.rb +0 -61
- data/lib/igniter/compiler/validation_pipeline.rb +0 -32
- data/lib/igniter/compiler/validator.rb +0 -19
- data/lib/igniter/compiler/validators/await_validator.rb +0 -53
- data/lib/igniter/compiler/validators/callable_validator.rb +0 -125
- data/lib/igniter/compiler/validators/dependencies_validator.rb +0 -241
- data/lib/igniter/compiler/validators/outputs_validator.rb +0 -66
- data/lib/igniter/compiler/validators/remote_validator.rb +0 -60
- data/lib/igniter/compiler/validators/type_compatibility_validator.rb +0 -84
- data/lib/igniter/compiler/validators/uniqueness_validator.rb +0 -60
- data/lib/igniter/compiler.rb +0 -20
- data/lib/igniter/consensus/cluster.rb +0 -183
- data/lib/igniter/consensus/errors.rb +0 -14
- data/lib/igniter/consensus/executors.rb +0 -43
- data/lib/igniter/consensus/node.rb +0 -320
- data/lib/igniter/consensus/read_query.rb +0 -30
- data/lib/igniter/consensus/state_machine.rb +0 -58
- data/lib/igniter/consensus.rb +0 -58
- data/lib/igniter/content_addressing.rb +0 -133
- data/lib/igniter/dataflow/aggregate_operators.rb +0 -147
- data/lib/igniter/dataflow/aggregate_state.rb +0 -77
- data/lib/igniter/dataflow/diff.rb +0 -37
- data/lib/igniter/dataflow/diff_state.rb +0 -81
- data/lib/igniter/dataflow/incremental_collection_result.rb +0 -39
- data/lib/igniter/dataflow/window_filter.rb +0 -48
- data/lib/igniter/dataflow.rb +0 -65
- data/lib/igniter/diagnostics/auditing/report/console_formatter.rb +0 -80
- data/lib/igniter/diagnostics/auditing/report/markdown_formatter.rb +0 -22
- data/lib/igniter/diagnostics/introspection/formatters/mermaid_formatter.rb +0 -58
- data/lib/igniter/diagnostics/introspection/formatters/text_tree_formatter.rb +0 -44
- data/lib/igniter/diagnostics/report.rb +0 -349
- data/lib/igniter/diagnostics.rb +0 -8
- data/lib/igniter/differential/divergence.rb +0 -29
- data/lib/igniter/differential/formatter.rb +0 -96
- data/lib/igniter/differential/report.rb +0 -86
- data/lib/igniter/differential/runner.rb +0 -130
- data/lib/igniter/differential.rb +0 -51
- data/lib/igniter/dsl/contract_builder.rb +0 -495
- data/lib/igniter/dsl/schema_builder.rb +0 -73
- data/lib/igniter/dsl.rb +0 -9
- data/lib/igniter/effect.rb +0 -91
- data/lib/igniter/effect_registry.rb +0 -78
- data/lib/igniter/errors.rb +0 -79
- data/lib/igniter/events/bus.rb +0 -44
- data/lib/igniter/events/event.rb +0 -82
- data/lib/igniter/events.rb +0 -9
- data/lib/igniter/execution_report/builder.rb +0 -54
- data/lib/igniter/execution_report/formatter.rb +0 -50
- data/lib/igniter/execution_report/node_entry.rb +0 -24
- data/lib/igniter/execution_report/report.rb +0 -65
- data/lib/igniter/execution_report.rb +0 -32
- data/lib/igniter/executor.rb +0 -134
- data/lib/igniter/executor_registry.rb +0 -44
- data/lib/igniter/extensions/auditing/timeline.rb +0 -103
- data/lib/igniter/extensions/auditing.rb +0 -10
- data/lib/igniter/extensions/capabilities.rb +0 -39
- data/lib/igniter/extensions/content_addressing.rb +0 -5
- data/lib/igniter/extensions/dataflow.rb +0 -117
- data/lib/igniter/extensions/differential.rb +0 -114
- data/lib/igniter/extensions/execution_report.rb +0 -27
- data/lib/igniter/extensions/incremental.rb +0 -50
- data/lib/igniter/extensions/introspection/graph_formatter.rb +0 -103
- data/lib/igniter/extensions/introspection/plan_formatter.rb +0 -55
- data/lib/igniter/extensions/introspection/runtime_formatter.rb +0 -117
- data/lib/igniter/extensions/introspection.rb +0 -12
- data/lib/igniter/extensions/invariants.rb +0 -116
- data/lib/igniter/extensions/mesh.rb +0 -31
- data/lib/igniter/extensions/provenance.rb +0 -45
- data/lib/igniter/extensions/reactive/engine.rb +0 -83
- data/lib/igniter/extensions/reactive/matcher.rb +0 -21
- data/lib/igniter/extensions/reactive/reaction.rb +0 -18
- data/lib/igniter/extensions/reactive.rb +0 -12
- data/lib/igniter/extensions/saga.rb +0 -74
- data/lib/igniter/extensions.rb +0 -10
- data/lib/igniter/fingerprint.rb +0 -43
- data/lib/igniter/incremental/formatter.rb +0 -81
- data/lib/igniter/incremental/result.rb +0 -69
- data/lib/igniter/incremental/tracker.rb +0 -108
- data/lib/igniter/incremental.rb +0 -50
- data/lib/igniter/integrations/agents.rb +0 -18
- data/lib/igniter/integrations/llm/config.rb +0 -113
- data/lib/igniter/integrations/llm/context.rb +0 -74
- data/lib/igniter/integrations/llm/executor.rb +0 -352
- data/lib/igniter/integrations/llm/providers/anthropic.rb +0 -181
- data/lib/igniter/integrations/llm/providers/base.rb +0 -33
- data/lib/igniter/integrations/llm/providers/ollama.rb +0 -137
- data/lib/igniter/integrations/llm/providers/openai.rb +0 -182
- data/lib/igniter/integrations/llm/transcription/providers/assemblyai.rb +0 -200
- data/lib/igniter/integrations/llm/transcription/providers/base.rb +0 -122
- data/lib/igniter/integrations/llm/transcription/providers/deepgram.rb +0 -162
- data/lib/igniter/integrations/llm/transcription/providers/openai.rb +0 -102
- data/lib/igniter/integrations/llm/transcription/transcriber.rb +0 -145
- data/lib/igniter/integrations/llm/transcription/transcript_result.rb +0 -29
- data/lib/igniter/integrations/llm.rb +0 -95
- data/lib/igniter/integrations/rails/cable_adapter.rb +0 -49
- data/lib/igniter/integrations/rails/contract_job.rb +0 -76
- data/lib/igniter/integrations/rails/generators/contract/contract_generator.rb +0 -22
- data/lib/igniter/integrations/rails/generators/install/install_generator.rb +0 -33
- data/lib/igniter/integrations/rails/railtie.rb +0 -25
- data/lib/igniter/integrations/rails/webhook_concern.rb +0 -49
- data/lib/igniter/integrations/rails.rb +0 -12
- data/lib/igniter/invariant.rb +0 -50
- data/lib/igniter/memory/agent_memory.rb +0 -104
- data/lib/igniter/memory/episode.rb +0 -29
- data/lib/igniter/memory/fact.rb +0 -27
- data/lib/igniter/memory/memorable.rb +0 -90
- data/lib/igniter/memory/reflection_cycle.rb +0 -96
- data/lib/igniter/memory/reflection_record.rb +0 -28
- data/lib/igniter/memory/store.rb +0 -115
- data/lib/igniter/memory/stores/in_memory.rb +0 -136
- data/lib/igniter/memory/stores/sqlite.rb +0 -284
- data/lib/igniter/memory.rb +0 -80
- data/lib/igniter/mesh/announcer.rb +0 -55
- data/lib/igniter/mesh/config.rb +0 -45
- data/lib/igniter/mesh/discovery.rb +0 -39
- data/lib/igniter/mesh/errors.rb +0 -31
- data/lib/igniter/mesh/gossip.rb +0 -47
- data/lib/igniter/mesh/peer.rb +0 -21
- data/lib/igniter/mesh/peer_registry.rb +0 -51
- data/lib/igniter/mesh/poller.rb +0 -77
- data/lib/igniter/mesh/router.rb +0 -109
- data/lib/igniter/mesh.rb +0 -85
- data/lib/igniter/metrics/collector.rb +0 -131
- data/lib/igniter/metrics/prometheus_exporter.rb +0 -104
- data/lib/igniter/metrics/snapshot.rb +0 -8
- data/lib/igniter/metrics.rb +0 -37
- data/lib/igniter/model/aggregate_node.rb +0 -34
- data/lib/igniter/model/await_node.rb +0 -21
- data/lib/igniter/model/branch_node.rb +0 -46
- data/lib/igniter/model/collection_node.rb +0 -32
- data/lib/igniter/model/composition_node.rb +0 -22
- data/lib/igniter/model/compute_node.rb +0 -90
- data/lib/igniter/model/effect_node.rb +0 -37
- data/lib/igniter/model/graph.rb +0 -15
- data/lib/igniter/model/input_node.rb +0 -27
- data/lib/igniter/model/node.rb +0 -22
- data/lib/igniter/model/output_node.rb +0 -41
- data/lib/igniter/model/remote_node.rb +0 -42
- data/lib/igniter/model.rb +0 -18
- data/lib/igniter/node_cache.rb +0 -231
- data/lib/igniter/property_testing/formatter.rb +0 -66
- data/lib/igniter/property_testing/generators.rb +0 -115
- data/lib/igniter/property_testing/result.rb +0 -45
- data/lib/igniter/property_testing/run.rb +0 -43
- data/lib/igniter/property_testing/runner.rb +0 -47
- data/lib/igniter/property_testing.rb +0 -64
- data/lib/igniter/provenance/builder.rb +0 -97
- data/lib/igniter/provenance/lineage.rb +0 -82
- data/lib/igniter/provenance/node_trace.rb +0 -65
- data/lib/igniter/provenance/text_formatter.rb +0 -70
- data/lib/igniter/provenance.rb +0 -29
- data/lib/igniter/registry.rb +0 -67
- data/lib/igniter/replication/bootstrapper.rb +0 -61
- data/lib/igniter/replication/bootstrappers/gem.rb +0 -32
- data/lib/igniter/replication/bootstrappers/git.rb +0 -39
- data/lib/igniter/replication/bootstrappers/tarball.rb +0 -56
- data/lib/igniter/replication/expansion_plan.rb +0 -38
- data/lib/igniter/replication/expansion_planner.rb +0 -142
- data/lib/igniter/replication/manifest.rb +0 -45
- data/lib/igniter/replication/network_topology.rb +0 -123
- data/lib/igniter/replication/node_role.rb +0 -42
- data/lib/igniter/replication/reflective_replication_agent.rb +0 -238
- data/lib/igniter/replication/replication_agent.rb +0 -87
- data/lib/igniter/replication/role_registry.rb +0 -73
- data/lib/igniter/replication/ssh_session.rb +0 -77
- data/lib/igniter/replication.rb +0 -54
- data/lib/igniter/runtime/cache.rb +0 -126
- data/lib/igniter/runtime/collection_result.rb +0 -111
- data/lib/igniter/runtime/deferred_result.rb +0 -40
- data/lib/igniter/runtime/execution.rb +0 -416
- data/lib/igniter/runtime/input_validator.rb +0 -129
- data/lib/igniter/runtime/invalidator.rb +0 -52
- data/lib/igniter/runtime/job_worker.rb +0 -18
- data/lib/igniter/runtime/node_state.rb +0 -56
- data/lib/igniter/runtime/planner.rb +0 -126
- data/lib/igniter/runtime/resolver.rb +0 -758
- data/lib/igniter/runtime/result.rb +0 -117
- data/lib/igniter/runtime/runner_factory.rb +0 -20
- data/lib/igniter/runtime/runners/inline_runner.rb +0 -21
- data/lib/igniter/runtime/runners/store_runner.rb +0 -29
- data/lib/igniter/runtime/runners/thread_pool_runner.rb +0 -37
- data/lib/igniter/runtime/stores/active_record_store.rb +0 -53
- data/lib/igniter/runtime/stores/file_store.rb +0 -91
- data/lib/igniter/runtime/stores/memory_store.rb +0 -93
- data/lib/igniter/runtime/stores/redis_store.rb +0 -93
- data/lib/igniter/runtime.rb +0 -26
- data/lib/igniter/saga/compensation.rb +0 -31
- data/lib/igniter/saga/compensation_record.rb +0 -20
- data/lib/igniter/saga/executor.rb +0 -85
- data/lib/igniter/saga/formatter.rb +0 -49
- data/lib/igniter/saga/result.rb +0 -47
- data/lib/igniter/saga.rb +0 -56
- data/lib/igniter/server/client.rb +0 -166
- data/lib/igniter/server/config.rb +0 -34
- data/lib/igniter/server/handlers/base.rb +0 -105
- data/lib/igniter/server/handlers/contracts_handler.rb +0 -15
- data/lib/igniter/server/handlers/event_handler.rb +0 -32
- data/lib/igniter/server/handlers/execute_handler.rb +0 -43
- data/lib/igniter/server/handlers/health_handler.rb +0 -32
- data/lib/igniter/server/handlers/liveness_handler.rb +0 -20
- data/lib/igniter/server/handlers/manifest_handler.rb +0 -34
- data/lib/igniter/server/handlers/metrics_handler.rb +0 -51
- data/lib/igniter/server/handlers/peers_handler.rb +0 -115
- data/lib/igniter/server/handlers/readiness_handler.rb +0 -47
- data/lib/igniter/server/handlers/status_handler.rb +0 -27
- data/lib/igniter/server/http_server.rb +0 -146
- data/lib/igniter/server/rack_app.rb +0 -35
- data/lib/igniter/server/registry.rb +0 -56
- data/lib/igniter/server/router.rb +0 -108
- data/lib/igniter/server/server_logger.rb +0 -52
- data/lib/igniter/server.rb +0 -73
- data/lib/igniter/skill/feedback.rb +0 -116
- data/lib/igniter/skill/output_schema.rb +0 -110
- data/lib/igniter/skill.rb +0 -218
- data/lib/igniter/stream_loop.rb +0 -80
- data/lib/igniter/supervisor.rb +0 -167
- data/lib/igniter/temporal.rb +0 -84
- data/lib/igniter/tool/discoverable.rb +0 -151
- data/lib/igniter/tool.rb +0 -52
- data/lib/igniter/tool_registry.rb +0 -144
- data/lib/igniter/type_system.rb +0 -44
- /data/docs/{EXECUTION_MODEL_V2.md → dev/execution-model.md} +0 -0
data/docs/MESH_V1.md
DELETED
|
@@ -1,732 +0,0 @@
|
|
|
1
|
-
# Igniter Mesh — Phase 1: Static Mesh
|
|
2
|
-
|
|
3
|
-
> **Status**: v1 shipped (2026-04)
|
|
4
|
-
> **Require**: `require "igniter/extensions/mesh"`
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Overview
|
|
9
|
-
|
|
10
|
-
Igniter Mesh extends the `remote:` DSL with intelligent peer routing. Instead of hard-coding a
|
|
11
|
-
URL for every remote node, contracts can declare their **capability requirements**, and the mesh
|
|
12
|
-
router selects an alive peer automatically at runtime.
|
|
13
|
-
|
|
14
|
-
Phase 1 is a **static mesh** — the peer topology is declared once at startup (no gossip, no
|
|
15
|
-
dynamic discovery). Each peer advertises capabilities it can handle. The mesh router:
|
|
16
|
-
|
|
17
|
-
- **Probes peer health** before routing (5s TTL cache to avoid per-request overhead).
|
|
18
|
-
- **Load-balances** across alive peers using round-robin.
|
|
19
|
-
- **Defers gracefully** when no capable peer is alive — the node becomes `:pending` and retries
|
|
20
|
-
automatically when inputs are updated, rather than failing the whole graph.
|
|
21
|
-
- **Escalates to incident** for pinned (critical) nodes that must run on a specific peer.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Quick Start
|
|
26
|
-
|
|
27
|
-
```ruby
|
|
28
|
-
require "igniter/extensions/mesh"
|
|
29
|
-
|
|
30
|
-
# ── 1. Declare the peer topology ─────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
Igniter::Mesh.configure do |c|
|
|
33
|
-
c.peer_name = "api-node" # this node's identity
|
|
34
|
-
c.local_capabilities = [:api] # capabilities this node itself provides
|
|
35
|
-
|
|
36
|
-
c.add_peer "orders-node",
|
|
37
|
-
url: "http://orders.internal:4567",
|
|
38
|
-
capabilities: %i[orders inventory]
|
|
39
|
-
|
|
40
|
-
c.add_peer "audit-node",
|
|
41
|
-
url: "http://audit.internal:4567",
|
|
42
|
-
capabilities: %i[audit]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# ── 2. Advertise capabilities on the server side ──────────────────────────────
|
|
46
|
-
|
|
47
|
-
Igniter::Server.configure do |c|
|
|
48
|
-
c.peer_name = "orders-node"
|
|
49
|
-
c.peer_capabilities = %i[orders inventory]
|
|
50
|
-
c.register "ProcessOrder", ProcessOrderContract
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# ── 3. Route by capability (auto-select, deferred on failure) ─────────────────
|
|
54
|
-
|
|
55
|
-
class OrderPipeline < Igniter::Contract
|
|
56
|
-
define do
|
|
57
|
-
input :order_id
|
|
58
|
-
|
|
59
|
-
remote :order_result,
|
|
60
|
-
contract: "ProcessOrder",
|
|
61
|
-
capability: :orders, # auto-select any alive peer with :orders
|
|
62
|
-
inputs: { order_id: :order_id }
|
|
63
|
-
|
|
64
|
-
output :order_result
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# ── 4. Route by name (pinned, incident on failure) ────────────────────────────
|
|
69
|
-
|
|
70
|
-
class AuditPipeline < Igniter::Contract
|
|
71
|
-
define do
|
|
72
|
-
input :event
|
|
73
|
-
|
|
74
|
-
remote :audit_log,
|
|
75
|
-
contract: "WriteAudit",
|
|
76
|
-
pinned_to: "audit-node", # must use this exact peer
|
|
77
|
-
inputs: { event: :event }
|
|
78
|
-
|
|
79
|
-
output :audit_log
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Configuration
|
|
87
|
-
|
|
88
|
-
### `Igniter::Mesh.configure`
|
|
89
|
-
|
|
90
|
-
```ruby
|
|
91
|
-
Igniter::Mesh.configure do |c|
|
|
92
|
-
c.peer_name = "my-node" # String — this node's identity in the mesh
|
|
93
|
-
c.local_capabilities = %i[api search] # Symbols — capabilities this node provides
|
|
94
|
-
|
|
95
|
-
c.add_peer "peer-name",
|
|
96
|
-
url: "http://host:port",
|
|
97
|
-
capabilities: %i[orders inventory]
|
|
98
|
-
end
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
| Option | Type | Description |
|
|
102
|
-
|--------|------|-------------|
|
|
103
|
-
| `peer_name=` | String | Identity of the local node (used in manifest responses) |
|
|
104
|
-
| `local_capabilities=` | Array\<Symbol\> | Capabilities this node advertises |
|
|
105
|
-
| `add_peer(name, url:, capabilities: [])` | — | Register a remote peer |
|
|
106
|
-
|
|
107
|
-
### Reset
|
|
108
|
-
|
|
109
|
-
```ruby
|
|
110
|
-
Igniter::Mesh.reset! # clears config + router (useful in tests)
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## `remote:` Routing Modes
|
|
116
|
-
|
|
117
|
-
All three modes use the same `remote:` DSL keyword. Exactly one of `node:`, `capability:`, or
|
|
118
|
-
`pinned_to:` must be provided.
|
|
119
|
-
|
|
120
|
-
### `:static` — hard-coded URL (original behaviour)
|
|
121
|
-
|
|
122
|
-
```ruby
|
|
123
|
-
remote :result,
|
|
124
|
-
contract: "MyContract",
|
|
125
|
-
node: "http://scoring.internal:4567",
|
|
126
|
-
inputs: { value: :value }
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Behaviour unchanged from pre-mesh. Fails immediately if the peer is unreachable.
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
### `:capability` — auto-select an alive peer
|
|
134
|
-
|
|
135
|
-
```ruby
|
|
136
|
-
remote :result,
|
|
137
|
-
contract: "MyContract",
|
|
138
|
-
capability: :orders, # any alive peer advertising :orders
|
|
139
|
-
inputs: { order_id: :order_id }
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**Runtime behaviour:**
|
|
143
|
-
|
|
144
|
-
| Situation | Outcome |
|
|
145
|
-
|-----------|---------|
|
|
146
|
-
| At least one alive peer with the capability | Round-robin selection; contract executes normally |
|
|
147
|
-
| No alive peers (all down or none configured) | Node becomes **`:pending`**; graph continues resolving other nodes |
|
|
148
|
-
| `:pending` node retried on `resolve_all` | If a peer comes up, resolves normally; otherwise stays `:pending` |
|
|
149
|
-
|
|
150
|
-
A pending `capability:` node does **not** fail the graph — it's treated the same as a dependency
|
|
151
|
-
that hasn't arrived yet. This enables graceful degradation and retry-on-recovery patterns.
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
### `:pinned` — must use a specific named peer
|
|
156
|
-
|
|
157
|
-
```ruby
|
|
158
|
-
remote :audit_log,
|
|
159
|
-
contract: "WriteAudit",
|
|
160
|
-
pinned_to: "audit-node", # exactly this peer, no fallback
|
|
161
|
-
inputs: { event: :event }
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
**Runtime behaviour:**
|
|
165
|
-
|
|
166
|
-
| Situation | Outcome |
|
|
167
|
-
|-----------|---------|
|
|
168
|
-
| Named peer is alive | Executes normally |
|
|
169
|
-
| Named peer is down | Node becomes **`:failed`** with `Igniter::Mesh::IncidentError` |
|
|
170
|
-
| Named peer is not registered | Node becomes **`:failed`** with `Igniter::Mesh::IncidentError` |
|
|
171
|
-
|
|
172
|
-
Use `pinned_to:` for critical side-effects (audit trails, payment processors, authoritative
|
|
173
|
-
records) that must not be load-balanced and must alert an operator when unavailable.
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Error Types
|
|
178
|
-
|
|
179
|
-
### `Igniter::Mesh::DeferredCapabilityError`
|
|
180
|
-
|
|
181
|
-
Raised internally by `Mesh::Router#find_peer_for` when no alive peer has the requested
|
|
182
|
-
capability. Inherits from `Igniter::PendingDependencyError`, so the runtime's existing
|
|
183
|
-
`rescue PendingDependencyError` branch catches it and transitions the node to `:pending`.
|
|
184
|
-
|
|
185
|
-
```ruby
|
|
186
|
-
rescue Igniter::Mesh::DeferredCapabilityError => e
|
|
187
|
-
e.capability # => :orders
|
|
188
|
-
e.message # => "No alive peer with capability :orders"
|
|
189
|
-
end
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### `Igniter::Mesh::IncidentError`
|
|
193
|
-
|
|
194
|
-
Raised internally by `Mesh::Router#resolve_pinned` when the pinned peer is unknown or
|
|
195
|
-
unreachable. Inherits from `Igniter::ResolutionError < StandardError`, so the runtime's
|
|
196
|
-
existing `rescue StandardError` branch catches it and transitions the node to `:failed`.
|
|
197
|
-
|
|
198
|
-
```ruby
|
|
199
|
-
rescue Igniter::Mesh::IncidentError => e
|
|
200
|
-
e.peer_name # => "audit-node"
|
|
201
|
-
e.message # => "Pinned peer 'audit-node' is unreachable — manual intervention required"
|
|
202
|
-
end
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Health Routing — `Mesh::Router`
|
|
208
|
-
|
|
209
|
-
The router is obtained via `Igniter::Mesh.router` (lazy-initialized, thread-safe).
|
|
210
|
-
|
|
211
|
-
### Health cache
|
|
212
|
-
|
|
213
|
-
To avoid a health-check HTTP call on every node resolution, each peer's alive/dead status is
|
|
214
|
-
cached for **5 seconds** (configurable via `Mesh::Router::HEALTH_CACHE_TTL`).
|
|
215
|
-
|
|
216
|
-
```
|
|
217
|
-
First resolution → health check → cache entry { alive: true, checked_at: now }
|
|
218
|
-
Subsequent (< 5s) → cache hit, no HTTP call
|
|
219
|
-
After 5s → cache expires → next resolution triggers a new health check
|
|
220
|
-
After request failure → call invalidate_health!(url) to force re-check immediately
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Round-robin
|
|
224
|
-
|
|
225
|
-
Across multiple alive peers sharing the same capability, the router selects peers using a
|
|
226
|
-
per-capability counter (`(counter % alive_count)th` peer). The counter increments on each
|
|
227
|
-
selection and is never reset, providing even distribution over time.
|
|
228
|
-
|
|
229
|
-
### Manual operations
|
|
230
|
-
|
|
231
|
-
```ruby
|
|
232
|
-
router = Igniter::Mesh.router
|
|
233
|
-
|
|
234
|
-
# Expire a peer's health cache entry (e.g. after a known failure)
|
|
235
|
-
router.invalidate_health!("http://orders.internal:4567")
|
|
236
|
-
|
|
237
|
-
# Directly find a URL for a capability (raises DeferredCapabilityError if none alive)
|
|
238
|
-
url = router.find_peer_for(:orders, deferred_result)
|
|
239
|
-
|
|
240
|
-
# Directly resolve a pinned peer's URL (raises IncidentError if down/unknown)
|
|
241
|
-
url = router.resolve_pinned("audit-node")
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## Server — Peer Identity & Manifest
|
|
247
|
-
|
|
248
|
-
### Advertising capabilities
|
|
249
|
-
|
|
250
|
-
Configure the local server to declare its identity and capabilities:
|
|
251
|
-
|
|
252
|
-
```ruby
|
|
253
|
-
require "igniter/server"
|
|
254
|
-
|
|
255
|
-
Igniter::Server.configure do |c|
|
|
256
|
-
c.peer_name = "orders-node"
|
|
257
|
-
c.peer_capabilities = %i[orders inventory]
|
|
258
|
-
c.register "ProcessOrder", ProcessOrderContract
|
|
259
|
-
end
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### `GET /v1/manifest`
|
|
263
|
-
|
|
264
|
-
Returns a JSON description of the peer: its name, capabilities, registered contracts, and URL.
|
|
265
|
-
Used by other mesh nodes for peer discovery and health-probing.
|
|
266
|
-
|
|
267
|
-
**Response:**
|
|
268
|
-
```json
|
|
269
|
-
{
|
|
270
|
-
"peer_name": "orders-node",
|
|
271
|
-
"capabilities": ["orders", "inventory"],
|
|
272
|
-
"contracts": ["ProcessOrder"],
|
|
273
|
-
"url": "http://0.0.0.0:4567"
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### `Client#manifest`
|
|
278
|
-
|
|
279
|
-
Fetch a remote peer's manifest from application code:
|
|
280
|
-
|
|
281
|
-
```ruby
|
|
282
|
-
client = Igniter::Server::Client.new("http://orders.internal:4567")
|
|
283
|
-
info = client.manifest
|
|
284
|
-
# => { peer_name: "orders-node", capabilities: [:orders, :inventory],
|
|
285
|
-
# contracts: ["ProcessOrder"], url: "http://..." }
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## Architecture
|
|
291
|
-
|
|
292
|
-
```
|
|
293
|
-
DSL: remote(name, capability: / pinned_to: / node:)
|
|
294
|
-
│
|
|
295
|
-
▼
|
|
296
|
-
Model::RemoteNode
|
|
297
|
-
routing_mode → :static | :capability | :pinned
|
|
298
|
-
│
|
|
299
|
-
▼
|
|
300
|
-
Compiler::RemoteValidator
|
|
301
|
-
:static → validates node_url starts with http(s)://
|
|
302
|
-
:capability → validates capability is a Symbol
|
|
303
|
-
:pinned → validates pinned_to is a non-empty String
|
|
304
|
-
│
|
|
305
|
-
▼
|
|
306
|
-
Runtime::Resolver#resolve_remote_url(node)
|
|
307
|
-
:static → node.node_url (unchanged)
|
|
308
|
-
:capability → Igniter::Mesh.router.find_peer_for(cap, deferred_result)
|
|
309
|
-
✓ alive peer found → URL → execute via Client
|
|
310
|
-
✗ no alive peer → DeferredCapabilityError
|
|
311
|
-
→ existing rescue PendingDependencyError
|
|
312
|
-
→ NodeState(:pending)
|
|
313
|
-
:pinned → Igniter::Mesh.router.resolve_pinned(peer_name)
|
|
314
|
-
✓ alive → URL → execute via Client
|
|
315
|
-
✗ down / unknown → IncidentError
|
|
316
|
-
→ existing rescue StandardError
|
|
317
|
-
→ NodeState(:failed)
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
**Key invariant:** The mesh introduces zero new rescue branches in `resolver.rb`. Error
|
|
321
|
-
routing piggybacks entirely on the existing `PendingDependencyError` and `StandardError`
|
|
322
|
-
rescue chains.
|
|
323
|
-
|
|
324
|
-
---
|
|
325
|
-
|
|
326
|
-
## Multi-Node Topology Example
|
|
327
|
-
|
|
328
|
-
```
|
|
329
|
-
┌────────────────────────────────────────────────────────────────────┐
|
|
330
|
-
│ API Node :4567 │
|
|
331
|
-
│ capabilities: [:api] │
|
|
332
|
-
│ │
|
|
333
|
-
│ OrderPipeline │
|
|
334
|
-
│ remote :order_result, capability: :orders │
|
|
335
|
-
│ remote :audit_log, pinned_to: "audit-node" ─────────────┐ │
|
|
336
|
-
└──────────────────────────────┬─────────────────────────────────── ┼─┘
|
|
337
|
-
│ round-robin │
|
|
338
|
-
┌────────────────────┴────────────────────┐ │
|
|
339
|
-
▼ ▼ ▼
|
|
340
|
-
┌─────────────────────┐ ┌─────────────────────┐ ┌────────────────────┐
|
|
341
|
-
│ orders-node-1:4568 │ │ orders-node-2:4568 │ │ audit-node :4569 │
|
|
342
|
-
│ capabilities: │ │ capabilities: │ │ capabilities: │
|
|
343
|
-
│ [:orders, │ │ [:orders, │ │ [:audit] │
|
|
344
|
-
│ :inventory] │ │ :inventory] │ │ │
|
|
345
|
-
│ ProcessOrder │ │ ProcessOrder │ │ WriteAudit │
|
|
346
|
-
└─────────────────────┘ └─────────────────────┘ └────────────────────┘
|
|
347
|
-
|
|
348
|
-
↑ alive? cached 5s ↑ ↑ alive? cached 5s ↑ ↑ alive? cached 5s ↑
|
|
349
|
-
If both down → :pending If down → :pending If down → :failed (incident)
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
---
|
|
353
|
-
|
|
354
|
-
## Testing
|
|
355
|
-
|
|
356
|
-
Use `Igniter::Mesh.reset!` in `after` hooks to isolate tests:
|
|
357
|
-
|
|
358
|
-
```ruby
|
|
359
|
-
require "igniter/extensions/mesh"
|
|
360
|
-
|
|
361
|
-
RSpec.describe "OrderPipeline" do
|
|
362
|
-
after { Igniter::Mesh.reset! }
|
|
363
|
-
|
|
364
|
-
it "resolves via alive peer" do
|
|
365
|
-
# Stub the HTTP client
|
|
366
|
-
stub_client = instance_double(Igniter::Server::Client)
|
|
367
|
-
allow(stub_client).to receive(:health).and_return({ "status" => "ok" })
|
|
368
|
-
allow(stub_client).to receive(:execute).and_return(
|
|
369
|
-
{ status: :succeeded, outputs: { result: { id: 42, status: "processed" } } }
|
|
370
|
-
)
|
|
371
|
-
allow(Igniter::Server::Client).to receive(:new).and_return(stub_client)
|
|
372
|
-
|
|
373
|
-
Igniter::Mesh.configure do |c|
|
|
374
|
-
c.add_peer "orders-node",
|
|
375
|
-
url: "http://orders.internal:4567",
|
|
376
|
-
capabilities: [:orders]
|
|
377
|
-
end
|
|
378
|
-
|
|
379
|
-
contract = OrderPipeline.new(order_id: 42)
|
|
380
|
-
contract.resolve_all
|
|
381
|
-
expect(contract.result.order_result[:status]).to eq("processed")
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
it "defers when no peer is alive" do
|
|
385
|
-
dead_client = instance_double(Igniter::Server::Client)
|
|
386
|
-
allow(dead_client).to receive(:health)
|
|
387
|
-
.and_raise(Igniter::Server::Client::ConnectionError, "refused")
|
|
388
|
-
allow(Igniter::Server::Client).to receive(:new).and_return(dead_client)
|
|
389
|
-
|
|
390
|
-
Igniter::Mesh.configure do |c|
|
|
391
|
-
c.add_peer "orders-node",
|
|
392
|
-
url: "http://orders.internal:4567",
|
|
393
|
-
capabilities: [:orders]
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
contract = OrderPipeline.new(order_id: 42)
|
|
397
|
-
begin; contract.resolve_all; rescue Igniter::Error; nil; end
|
|
398
|
-
|
|
399
|
-
state = contract.execution.cache.fetch(:order_result)
|
|
400
|
-
expect(state&.status).to eq(:pending)
|
|
401
|
-
end
|
|
402
|
-
end
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
## Compile-Time Validation
|
|
408
|
-
|
|
409
|
-
The compiler validates mesh routing options before any contract executes:
|
|
410
|
-
|
|
411
|
-
| Violation | Error |
|
|
412
|
-
|-----------|-------|
|
|
413
|
-
| `capability:` and `pinned_to:` both provided | `CompileError` — mutually exclusive |
|
|
414
|
-
| None of `node:`, `capability:`, `pinned_to:` provided | `CompileError` — one required |
|
|
415
|
-
| `capability:` is not a Symbol | `ValidationError` |
|
|
416
|
-
| `pinned_to:` is an empty string | `ValidationError` |
|
|
417
|
-
| `node:` does not start with `http://` or `https://` | `ValidationError` |
|
|
418
|
-
|
|
419
|
-
---
|
|
420
|
-
|
|
421
|
-
---
|
|
422
|
-
|
|
423
|
-
## Phase 2 — Dynamic Discovery
|
|
424
|
-
|
|
425
|
-
> **Status**: v2 shipped (2026-04)
|
|
426
|
-
|
|
427
|
-
Eliminates the need for static `add_peer` declarations. Every peer acts as a registry,
|
|
428
|
-
stores the known peer list, and exposes it at `GET /v1/mesh/peers`.
|
|
429
|
-
|
|
430
|
-
### Configuration
|
|
431
|
-
|
|
432
|
-
```ruby
|
|
433
|
-
Igniter::Mesh.configure do |c|
|
|
434
|
-
c.peer_name = "api-node"
|
|
435
|
-
c.local_url = "http://api.internal:4567" # how OTHER peers reach this node
|
|
436
|
-
c.local_capabilities = %i[api]
|
|
437
|
-
c.seeds = %w[http://orders.internal:4567 http://audit.internal:4567]
|
|
438
|
-
c.discovery_interval = 30 # seconds between polls (default)
|
|
439
|
-
c.auto_announce = true # announce self to seeds at startup (default)
|
|
440
|
-
|
|
441
|
-
# Static peers still work alongside dynamic discovery:
|
|
442
|
-
c.add_peer "legacy-node", url: "http://legacy.internal:4567", capabilities: %i[billing]
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
Igniter::Mesh.start_discovery! # announce + poll + background thread
|
|
446
|
-
# …on graceful shutdown:
|
|
447
|
-
Igniter::Mesh.stop_discovery! # deannounce + stop background thread
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### `Igniter::Mesh.start_discovery!`
|
|
451
|
-
|
|
452
|
-
Performs three steps synchronously:
|
|
453
|
-
|
|
454
|
-
1. **Announce** — POSTs self-manifest to each seed (`POST /v1/mesh/peers`).
|
|
455
|
-
2. **Immediate poll** — fetches `GET /v1/mesh/peers` from each seed and populates
|
|
456
|
-
the local `PeerRegistry` with newly discovered peers.
|
|
457
|
-
3. **Background poller** — starts a thread that repeats the poll every `discovery_interval` seconds.
|
|
458
|
-
|
|
459
|
-
Returns `Igniter::Mesh` (chainable).
|
|
460
|
-
|
|
461
|
-
### `Igniter::Mesh.stop_discovery!`
|
|
462
|
-
|
|
463
|
-
1. **Deannounce** — sends `DELETE /v1/mesh/peers/:name` to each seed (best-effort).
|
|
464
|
-
2. Stops the background polling thread.
|
|
465
|
-
|
|
466
|
-
### Peer registry endpoints
|
|
467
|
-
|
|
468
|
-
| Endpoint | Method | Description |
|
|
469
|
-
|----------|--------|-------------|
|
|
470
|
-
| `GET /v1/mesh/peers` | GET | List all known peers (static + dynamic, merged) |
|
|
471
|
-
| `POST /v1/mesh/peers` | POST | Register a peer in this node's dynamic registry |
|
|
472
|
-
| `DELETE /v1/mesh/peers/:name` | DELETE | Deregister a peer by name (idempotent) |
|
|
473
|
-
|
|
474
|
-
**POST body:**
|
|
475
|
-
```json
|
|
476
|
-
{ "name": "orders-node", "url": "http://orders.internal:4567", "capabilities": ["orders"] }
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
**GET response:**
|
|
480
|
-
```json
|
|
481
|
-
[
|
|
482
|
-
{ "name": "orders-node", "url": "http://orders.internal:4567", "capabilities": ["orders"] },
|
|
483
|
-
{ "name": "legacy-node", "url": "http://legacy.internal:4567", "capabilities": ["billing"] }
|
|
484
|
-
]
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
### Static + dynamic peer merge
|
|
488
|
-
|
|
489
|
-
The `Router` and `GET /v1/mesh/peers` both merge static and dynamic peers:
|
|
490
|
-
|
|
491
|
-
- Static peers (`add_peer`) take **precedence** — if a static and dynamic peer share
|
|
492
|
-
the same name, the static entry wins.
|
|
493
|
-
- Dynamic-only peers are appended after all static peers.
|
|
494
|
-
|
|
495
|
-
### `PeerRegistry`
|
|
496
|
-
|
|
497
|
-
Thread-safe registry for dynamically discovered peers. Available at
|
|
498
|
-
`Igniter::Mesh.config.peer_registry`:
|
|
499
|
-
|
|
500
|
-
```ruby
|
|
501
|
-
reg = Igniter::Mesh.config.peer_registry
|
|
502
|
-
|
|
503
|
-
reg.register(Igniter::Mesh::Peer.new(name: "x", url: "http://x:4567", capabilities: [:orders]))
|
|
504
|
-
reg.unregister("x") # idempotent
|
|
505
|
-
reg.all # → Array<Peer> snapshot
|
|
506
|
-
reg.peer_named("x") # → Peer | nil
|
|
507
|
-
reg.peers_with_capability(:orders) # → Array<Peer>
|
|
508
|
-
reg.size # → Integer
|
|
509
|
-
reg.clear # (useful in tests)
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
### `Client` mesh methods
|
|
513
|
-
|
|
514
|
-
```ruby
|
|
515
|
-
client = Igniter::Server::Client.new("http://seed:4567")
|
|
516
|
-
|
|
517
|
-
client.list_peers
|
|
518
|
-
# => [{ name: "orders-node", url: "http://...", capabilities: [:orders] }, ...]
|
|
519
|
-
|
|
520
|
-
client.register_peer(name: "api-node", url: "http://api:4567", capabilities: %i[api])
|
|
521
|
-
# => { "registered" => true, "name" => "api-node" }
|
|
522
|
-
|
|
523
|
-
client.unregister_peer("api-node")
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
### Topology diagram (Phase 2)
|
|
527
|
-
|
|
528
|
-
```
|
|
529
|
-
Node A starts:
|
|
530
|
-
Igniter::Mesh.start_discovery!(seeds: ["http://seed:4567"])
|
|
531
|
-
→ POST /v1/mesh/peers to seed (self-announce)
|
|
532
|
-
→ GET /v1/mesh/peers from seed (immediate poll → fills PeerRegistry)
|
|
533
|
-
→ background thread polls seed every 30s
|
|
534
|
-
|
|
535
|
-
Node B starts later:
|
|
536
|
-
same flow → also announces to seed
|
|
537
|
-
Next poll on Node A → discovers Node B → added to PeerRegistry
|
|
538
|
-
Node A's capability routing now includes Node B
|
|
539
|
-
|
|
540
|
-
Node C goes offline:
|
|
541
|
-
Health cache expires → alive?(C) returns false → C skipped in routing
|
|
542
|
-
C's entry stays in PeerRegistry (no auto-remove) — will route again if C recovers
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
---
|
|
546
|
-
|
|
547
|
-
## Phase 3 — Gossip Protocol
|
|
548
|
-
|
|
549
|
-
> **Status**: v1 shipped (2026-04)
|
|
550
|
-
|
|
551
|
-
### Motivation
|
|
552
|
-
|
|
553
|
-
Phase 2 seeds act as soft coordinators — topology is only as complete as the seeds know.
|
|
554
|
-
If a seed goes offline after bootstrapping, peers can still communicate, but new nodes
|
|
555
|
-
cannot be discovered. Phase 3 adds **peer-to-peer gossip**: after each seed poll, every
|
|
556
|
-
node also exchanges its peer list with N randomly chosen nodes from its own registry.
|
|
557
|
-
This makes topology convergence faster, decentralised, and resilient to seed failure.
|
|
558
|
-
|
|
559
|
-
### How It Works
|
|
560
|
-
|
|
561
|
-
```
|
|
562
|
-
Each poll_once cycle (every discovery_interval seconds):
|
|
563
|
-
1. Seed poll: GET /v1/mesh/peers from each seed → register returned peers (Phase 2)
|
|
564
|
-
2. Gossip round: pick min(gossip_fanout, registry.size) random registry peers
|
|
565
|
-
GET /v1/mesh/peers on each → register returned peers (Phase 3)
|
|
566
|
-
```
|
|
567
|
-
|
|
568
|
-
No new server endpoints are introduced. Gossip reuses the existing `GET /v1/mesh/peers`
|
|
569
|
-
endpoint from Phase 2.
|
|
570
|
-
|
|
571
|
-
### Convergence Example
|
|
572
|
-
|
|
573
|
-
```
|
|
574
|
-
Seed knows [A, B, C] → after bootstrap, every node knows A, B, C
|
|
575
|
-
Seed goes down → Phase 2 can't discover new peer D
|
|
576
|
-
D joins, announces → seed down, but D's poller is running
|
|
577
|
-
E polls seed (empty), then gossips with A → E discovers D ← Phase 3 win
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
With fanout = 3 in a 10-node mesh, each node contacts 3 random peers per round.
|
|
581
|
-
After ~2 rounds every node has high probability of knowing any new peer.
|
|
582
|
-
|
|
583
|
-
### Configuration
|
|
584
|
-
|
|
585
|
-
```ruby
|
|
586
|
-
Igniter::Mesh.configure do |c|
|
|
587
|
-
c.peer_name = "api-node"
|
|
588
|
-
c.local_url = "http://api.internal:4567"
|
|
589
|
-
c.seeds = %w[http://seed:4567]
|
|
590
|
-
c.discovery_interval = 30
|
|
591
|
-
c.gossip_fanout = 3 # random peers per gossip round (default 3, 0 = disabled)
|
|
592
|
-
end
|
|
593
|
-
|
|
594
|
-
Igniter::Mesh.start_discovery!
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
| Option | Default | Description |
|
|
598
|
-
|--------|---------|-------------|
|
|
599
|
-
| `gossip_fanout` | `3` | Number of random registry peers to contact per gossip round. Set to `0` to disable gossip entirely. |
|
|
600
|
-
|
|
601
|
-
### `GossipRound` API
|
|
602
|
-
|
|
603
|
-
`GossipRound` is a plain object created and invoked automatically by `Poller#poll_once`,
|
|
604
|
-
but you can also call it directly (e.g. for a one-off topology refresh):
|
|
605
|
-
|
|
606
|
-
```ruby
|
|
607
|
-
Igniter::Mesh::GossipRound.new(Igniter::Mesh.config).run
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
**Behaviour:**
|
|
611
|
-
- Picks `min(gossip_fanout, registry.size)` random peers, excluding self (by `local_url`).
|
|
612
|
-
- Fetches `GET /v1/mesh/peers` from each candidate.
|
|
613
|
-
- Skips entries with `nil` name or `nil` url, and skips self (by `peer_name` match).
|
|
614
|
-
- Registers newly discovered peers in `PeerRegistry` (idempotent — latest version wins).
|
|
615
|
-
- Swallows `ConnectionError` per peer — a dead peer must not abort the round.
|
|
616
|
-
|
|
617
|
-
### Example
|
|
618
|
-
|
|
619
|
-
See `examples/mesh_gossip.rb` for a 3-node scenario: A knows B, C only knows A. After
|
|
620
|
-
a single gossip round C discovers B without any seed involvement.
|
|
621
|
-
|
|
622
|
-
### Topology Diagram (Phase 3)
|
|
623
|
-
|
|
624
|
-
```
|
|
625
|
-
Seed goes offline after bootstrap:
|
|
626
|
-
Node A: registry = {B, C}
|
|
627
|
-
Node B: registry = {A, C}
|
|
628
|
-
Node C: registry = {A, B}
|
|
629
|
-
|
|
630
|
-
New node D announces itself to seed (seed accepts, but is unreachable to others):
|
|
631
|
-
Only D's local registry has {D}
|
|
632
|
-
|
|
633
|
-
Next gossip round on Node A:
|
|
634
|
-
A picks B and C at random, fetches their lists
|
|
635
|
-
B returns {A, C, D} ← D has gossiped with B already
|
|
636
|
-
A registers D → A now knows D
|
|
637
|
-
|
|
638
|
-
Next gossip round on Node E (new node, only knows seed):
|
|
639
|
-
Seed is down → seed poll returns []
|
|
640
|
-
E picks A from registry, fetches A's list
|
|
641
|
-
A returns {B, C, D} → E discovers all three
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
---
|
|
645
|
-
|
|
646
|
-
## Observability — Prometheus Service Discovery
|
|
647
|
-
|
|
648
|
-
> **Status**: v1 shipped (2026-04)
|
|
649
|
-
|
|
650
|
-
### Problem
|
|
651
|
-
|
|
652
|
-
Each node already exposes `GET /v1/metrics` (Prometheus text 0.0.4). In a dynamic mesh the
|
|
653
|
-
set of nodes changes as peers join/leave. Maintaining a static `prometheus.yml` target list
|
|
654
|
-
is fragile. `GET /v1/mesh/sd` solves this: Prometheus polls one stable endpoint and
|
|
655
|
-
automatically discovers all scrape targets as the topology changes.
|
|
656
|
-
|
|
657
|
-
### Endpoint
|
|
658
|
-
|
|
659
|
-
```
|
|
660
|
-
GET /v1/mesh/sd
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
Returns the current peer list (static `add_peer` + dynamic `PeerRegistry`, same merge logic
|
|
664
|
-
as `GET /v1/mesh/peers`) in **Prometheus HTTP SD format**. Self is not included (consistent
|
|
665
|
-
with `/v1/mesh/peers`). Returns `[]` when Mesh is not loaded.
|
|
666
|
-
|
|
667
|
-
### Response Format
|
|
668
|
-
|
|
669
|
-
```json
|
|
670
|
-
[
|
|
671
|
-
{
|
|
672
|
-
"targets": ["node-a:4567"],
|
|
673
|
-
"labels": {
|
|
674
|
-
"__meta_igniter_peer_name": "node-a",
|
|
675
|
-
"__meta_igniter_capabilities": "orders,inventory"
|
|
676
|
-
}
|
|
677
|
-
},
|
|
678
|
-
{
|
|
679
|
-
"targets": ["node-b:4567"],
|
|
680
|
-
"labels": {
|
|
681
|
-
"__meta_igniter_peer_name": "node-b",
|
|
682
|
-
"__meta_igniter_capabilities": "audit"
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
]
|
|
686
|
-
```
|
|
687
|
-
|
|
688
|
-
- `targets` — `host:port` extracted from the peer URL (scheme stripped).
|
|
689
|
-
- `__meta_igniter_peer_name` — peer name; available during Prometheus relabeling.
|
|
690
|
-
- `__meta_igniter_capabilities` — comma-separated capability list (empty string if none).
|
|
691
|
-
Labels with `__meta_` prefix are dropped after relabeling unless explicitly kept via
|
|
692
|
-
`relabel_configs`.
|
|
693
|
-
|
|
694
|
-
### Prometheus Configuration
|
|
695
|
-
|
|
696
|
-
Point `http_sd_configs` at any mesh node that has seed/gossip knowledge of the cluster.
|
|
697
|
-
Because topology propagates via gossip, any node works — no dedicated coordinator required.
|
|
698
|
-
|
|
699
|
-
```yaml
|
|
700
|
-
scrape_configs:
|
|
701
|
-
- job_name: igniter
|
|
702
|
-
http_sd_configs:
|
|
703
|
-
- url: http://any-seed:4567/v1/mesh/sd
|
|
704
|
-
refresh_interval: 30s # re-polls every 30s; matches default discovery_interval
|
|
705
|
-
metrics_path: /v1/metrics
|
|
706
|
-
# Optional: keep peer metadata as labels after scraping
|
|
707
|
-
relabel_configs:
|
|
708
|
-
- source_labels: [__meta_igniter_peer_name]
|
|
709
|
-
target_label: igniter_peer
|
|
710
|
-
- source_labels: [__meta_igniter_capabilities]
|
|
711
|
-
target_label: igniter_capabilities
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
### How Metrics Flow
|
|
715
|
-
|
|
716
|
-
```
|
|
717
|
-
Prometheus
|
|
718
|
-
→ GET /v1/mesh/sd (any seed, 30s refresh)
|
|
719
|
-
← [{ targets: ["node-a:4567"], ...}, { targets: ["node-b:4567"], ...}]
|
|
720
|
-
→ GET http://node-a:4567/v1/metrics (15s scrape)
|
|
721
|
-
→ GET http://node-b:4567/v1/metrics (15s scrape)
|
|
722
|
-
→ GET http://node-c:4567/v1/metrics (appears after gossip propagation)
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
New nodes are discovered within one gossip round + one SD refresh interval — typically
|
|
726
|
-
under 60 seconds in a default configuration.
|
|
727
|
-
|
|
728
|
-
---
|
|
729
|
-
|
|
730
|
-
## Roadmap
|
|
731
|
-
|
|
732
|
-
*(No further phases currently planned.)*
|