igniter-extensions
Contracts-native extension packs for Igniter.
This package now focuses only on packs built on top of Igniter::Contracts.
Primary entrypoints:
require "igniter-extensions"require "igniter/extensions/contracts"
Contracts-facing external packs now live here too:
Igniter::Extensions::Contracts::ExecutionReportPackIgniter::Extensions::Contracts::LookupPackIgniter::Extensions::Contracts::AggregatePackIgniter::Extensions::Contracts::AuditPackIgniter::Extensions::Contracts::BranchPackIgniter::Extensions::Contracts::CapabilitiesPackIgniter::Extensions::Contracts::CollectionPackIgniter::Extensions::Contracts::CommercePackIgniter::Extensions::Contracts::ComposePackIgniter::Extensions::Contracts::ContentAddressingPackIgniter::Extensions::Contracts::CreatorPackIgniter::Extensions::Contracts::DataflowPackIgniter::Extensions::Contracts::DebugPackIgniter::Extensions::Contracts::DifferentialPackIgniter::Extensions::Contracts::JournalPackIgniter::Extensions::Contracts::InvariantsPackIgniter::Extensions::Contracts::McpPackIgniter::Extensions::Contracts::ProvenancePackIgniter::Extensions::Contracts::ReactivePackIgniter::Extensions::Contracts::SagaPack
Those packs install into Igniter::Contracts through the public facade only:
require "igniter/extensions/contracts"
environment = Igniter::Extensions::Contracts.with
result = environment.run(inputs: { rates: { ua: 0.2 } }) do
input :rates
lookup :tax_rate, from: :rates, dig: %i[eu ua], default: 0.2
output :tax_rate
end
Default helpers like Igniter::Extensions::Contracts.with currently install the
safe default packs (ExecutionReportPack and LookupPack). Operational packs
like JournalPack stay opt-in:
environment = Igniter::Extensions::Contracts.with(
Igniter::Extensions::Contracts::JournalPack
)
BranchPack adds a contracts-native decision DSL that still lowers to ordinary
compute semantics:
environment = Igniter::Contracts.with(
Igniter::Contracts::ProjectPack,
Igniter::Extensions::Contracts::BranchPack
)
result = environment.run(inputs: { country: "DE", vip: true }) do
input :country
input :vip
branch :delivery_strategy, on: :country, depends_on: [:vip] do
on "UA", id: :local, value: :local
on matches: /\A[A-Z]{2}\z/, id: :international do |vip:|
vip ? :priority_international : :international
end
default value: :fallback
end
project :delivery_mode, from: :delivery_strategy, key: :value
output :delivery_mode
end
ComposePack adds explicit nested contract invocation without restoring legacy
composition semantics into the kernel:
environment = Igniter::Contracts.with(
Igniter::Extensions::Contracts::ComposePack
)
pricing_contract = environment.compile do
input :amount
input :tax_rate
compute :total, depends_on: %i[amount tax_rate] do |amount:, tax_rate:|
amount + (amount * tax_rate)
end
output :total
end
result = environment.run(inputs: { subtotal: 100, rate: 0.2 }) do
input :subtotal
input :rate
compose :pricing_total,
contract: pricing_contract,
inputs: { amount: :subtotal, tax_rate: :rate },
output: :total
output :pricing_total
end
The important forward-compatibility rule is that ComposePack keeps local
execution as the default, but also exposes via: for a custom invocation
adapter. That gives igniter-application or igniter-cluster room to add
remote compose later without rewriting the DSL contract.
CollectionPack follows the same idea for keyed collection execution:
environment = Igniter::Contracts.with(
Igniter::Extensions::Contracts::CollectionPack
)
result = environment.run(inputs: {
items: [{ sku: "a", amount: 10 }, { sku: "b", amount: 20 }],
tax_rate: 0.2
}) do
input :items
input :tax_rate
collection :priced_items, from: :items, key: :sku, inputs: { tax_rate: :tax_rate } do
input :sku
input :amount
input :tax_rate
compute :total, depends_on: %i[amount tax_rate] do |amount:, tax_rate:|
amount + (amount * tax_rate)
end
output :total
end
output :priced_items
end
It returns a CollectionResult keyed by item identity, and keeps via: open
for a future remote/distributed collection invoker without changing the user DSL.
Applied presets can sit on top of those packs too:
environment = Igniter::Extensions::Contracts.with_preset(:commerce)
For explicit content-addressed reuse, the contracts-side replacement is
ContentAddressingPack:
environment = Igniter::Contracts.with(
Igniter::Extensions::Contracts::ContentAddressingPack
)
tax = Igniter::Extensions::Contracts.content_addressed(
fingerprint: "tax_v1"
) do |country:, amount:|
{ ua: 0.2, us: 0.1 }.fetch(country) * amount
end
For developer-focused observability, DebugPack can bundle profile,
compilation, execution, diagnostics, and provenance into one report:
environment = Igniter::Extensions::Contracts.with(
Igniter::Extensions::Contracts::DebugPack
)
report = Igniter::Extensions::Contracts.debug_report(
environment,
inputs: { amount: 10 }
) do
input :amount
output :amount
end
It can also audit a custom pack before finalize, which is the first bridge
toward a future CreatorPack workflow:
audit = Igniter::Extensions::Contracts.audit_pack(MyDraftPack, environment)
audit.ok?
audit.missing_node_definitions
audit.missing_registry_contracts
audit.finalize_error
CreatorPack now adds a minimal scaffold/report workflow on top of that:
scaffold = Igniter::Extensions::Contracts.scaffold_pack(
name: :slug,
profile: :feature_node,
scope: :app_local,
namespace: "MyCompany::IgniterPacks"
)
report = Igniter::Extensions::Contracts.creator_report(
name: :slug,
profile: :feature_node
)
workflow = Igniter::Extensions::Contracts.creator_workflow(
name: :slug,
profile: :feature_node,
scope: :standalone_gem
)
Available authoring profiles:
:feature_node:operational_adapter:diagnostic_bundle:bundle_pack
Available target scopes:
:app_local:monorepo_package:standalone_gem
The workflow helper turns those decisions into an explicit authoring ladder:
- profile/scope selection
- scaffold generation
- implementation
- audit validation
- packaging readiness
It also separates recommended runtime dependency packs from development-only tooling packs, so authoring guidance does not accidentally become runtime bundle surface.
There is also a stateful wizard layer that can hold partial decisions before you are ready to generate files:
wizard = Igniter::Extensions::Contracts.creator_wizard(
name: :delivery,
capabilities: %i[effect executor]
)
wizard.current_decision
wizard.branching_hints
wizard.recommended_examples
completed = wizard.apply(scope: :standalone_gem)
For file generation, CreatorPack also exposes a multi-step writer with
explicit planning:
writer = Igniter::Extensions::Contracts.creator_writer(
name: :slug,
profile: :feature_node,
scope: :app_local,
root: "/tmp/my_pack"
)
plan = writer.plan
result = writer.write
By default the writer uses :skip_existing, so existing files are preserved
unless you explicitly opt into mode: :overwrite.
McpPack is the first thin tooling adapter over those stabilized surfaces:
environment = Igniter::Extensions::Contracts.with(
Igniter::Extensions::Contracts::McpPack
)
Igniter::Extensions::Contracts.mcp_tools
result = Igniter::Extensions::Contracts.mcp_call(
:creator_wizard,
target: environment,
name: :delivery,
capabilities: %i[effect executor]
)
The goal is to adapt existing debug/creator primitives for external tools, not to invent a second authoring stack.
For stepwise external tooling, McpPack also exposes a serialized
creator_session flow:
session = Igniter::Extensions::Contracts.mcp_creator_session(
target: environment,
name: :delivery,
capabilities: %i[effect executor]
)
updated = Igniter::Extensions::Contracts.mcp_call(
:creator_session_apply,
target: environment,
session: session.to_h.fetch(:payload).fetch(:session),
updates: { scope: :standalone_gem }
)
You can also drive scaffolding directly from capabilities:
Igniter::Extensions::Contracts.scaffold_pack(
name: :delivery,
capabilities: %i[effect executor]
)
Older extension activators still exist for migration scenarios:
require "igniter/extensions/auditing"require "igniter/extensions/capabilities"require "igniter/extensions/dataflow"require "igniter/extensions/saga"require "igniter/extensions/provenance"require "igniter/extensions/differential"require "igniter/extensions/incremental"require "igniter/extensions/reactive"require "igniter/extensions/invariants"
Those activators are migration context, not the long-term extension model.
The first canonical activator-to-pack migration target is now explicit:
require "igniter/extensions/execution_report"->Igniter::Extensions::Contracts::ExecutionReportPackrequire "igniter/extensions/auditing"->Igniter::Extensions::Contracts::AuditPackrequire "igniter/extensions/capabilities"->Igniter::Extensions::Contracts::CapabilitiesPackrequire "igniter/extensions/dataflow"->Igniter::Extensions::Contracts::DataflowPackrequire "igniter/extensions/provenance"->Igniter::Extensions::Contracts::ProvenancePackrequire "igniter/extensions/saga"->Igniter::Extensions::Contracts::SagaPackrequire "igniter/extensions/incremental"->Igniter::Extensions::Contracts::IncrementalPackrequire "igniter/extensions/differential"->Igniter::Extensions::Contracts::DifferentialPackrequire "igniter/extensions/reactive"->Igniter::Extensions::Contracts::ReactivePackrequire "igniter/extensions/invariants"->Igniter::Extensions::Contracts::InvariantsPack
See examples/contracts/auditing.rb and examples/contracts/capabilities.rb and examples/contracts/dataflow.rb and examples/contracts/differential.rb and examples/contracts/invariants.rb and examples/contracts/provenance.rb and examples/contracts/reactive.rb and examples/contracts/saga.rb and examples/contracts/incremental.rb for runnable migration walkthroughs.
Docs: