Packages

A BEAM-first process-mining substrate manufactured entirely by ggen from ontology.ttl + a vendored ggen-marketplace pack: real OCEL discovery/conformance across Erlang, Elixir, Gleam, and Ash projections, plus native engine facades (petgraph, tract, rust4pm, ferroplan) hosted in BEAM via wasm.

Current section

Files

Jump to
beam4pm README.md
Raw

README.md

# beam4pm

beam4pm is a BEAM-first process-mining substrate whose application source is
manufactured entirely by [ggen](https://github.com/seanchatmangpt/ggen) from an
RDF ontology and a vendored ggen-marketplace pack. There is no `generated/`
directory: manufactured code lives in the same `src/`, `lib/`, `test/`,
`gleam/`, `schema/`, and `docs/reference/` directories hand-authored code
would use — provenance is signalled per-file by a `GENERATED by ggen ... Do
not edit.` header, never by directory placement. `beam4pm_pro` is the planned
future commercial layer on top of this substrate; its core reconciliation
modules already exist as real code with matching test suites
(`beam4pm_billing`/`BeamPM.Billing`, MP6 usage/billing reconciliation;
`beam4pm_entitlement`/`BeamPM.Entitlement`, MP3 entitlement reconciliation) —
the remaining gap is marketplace/pricing/RevOps tooling, not these core
modules (`PRO_CAPABILITY_SEEDS: PARTIAL_ALIVE`), and no separately
installable/licensed `beam4pm_pro` product boundary, distribution channel, or
control plane exists yet (`PRO_PRODUCT_BOUNDARY: UNSUPPORTED`,
`PRO_DISTRIBUTION_AND_UPGRADE: UNSUPPORTED`, `PRO_CONTROL_PLANE: UNSUPPORTED`).
See [`docs/jira/v26.8.29/`](docs/jira/v26.8.29/) for the full doctrine, vision,
and RevOps package, and [`docs/v26.8.30/README.md`](docs/v26.8.30/README.md)
for the current gap-closure status and acceptance criteria.

## Source-authority doctrine

Direct edits to application source are refused by default, for humans and LLMs
alike. The only legitimate manufacturing inputs are `ontology.ttl`, `ggen.toml`,
`rebar.config`, `mix.exs`, `src/beam4pm.app.src`, and the templates inside the
vendored ggen-marketplace pack
(`vendor/ggen-marketplace/packs/beam4pm-process-model-pack`). Any file whose
first line reads `GENERATED by ggen ... Do not edit.` is ggen output and must
never be hand-edited, regardless of which directory it lives in — if it's
wrong, fix the ontology or the pack's templates and regenerate. See
[`docs/jira/v26.8.29/03-architecture-and-ggen-manufacturing.md`](docs/jira/v26.8.29/03-architecture-and-ggen-manufacturing.md)
for the full policy, including the narrow, receipted privileged-exception path
for direct intervention.

## Current status

A wide, still-growing slice, manufactured via the `beam4pm-process-model-pack`
(`vendor/ggen-marketplace/packs/beam4pm-process-model-pack`) from the
`bpm:RecordType` individuals currently admitted in `ontology.ttl` (981 as of
2026-09-27; the pre-WS2 slice was 290, and the merge-day 2026-09-27 merge
added 30 `bpm:aloop_*_rt` ALOOP episode-loop record types).

- 981 record types admitted in the graph (still 647 `Ash.Resource` modules —
  see below; the 30 ALOOP episode-loop record types added on merge-day
  2026-09-27 have no Ash projection yet). The original process-mining/runtime core is still there —
  event/log identity (`ocel_event`, `ocel_object`, `ocel_relationship`,
  `event_log`, `event_type`, `object_type`, `ocel_attribute`,
  `object_attribute_change`, `log_trace`), process models (`dfg_edge`,
  `petri_place`, `petri_transition`, `petri_arc`, `path_schema`,
  `path_schema_query`, `type_edge`, `heuristic_arc`), conformance/alignment
  (`alignment_move`, `conformance_result`, `oc_declare_constraint`,
  `process_variant`, `case_stats`, `sojourn_time`, `sync_time`), and adjacent
  runtime/planning/policy concepts (`resource_allocation`, `queue_snapshot`,
  `service_span`, `k8s_object_ref`, `planning_action`, `planning_state`,
  `policy_decision`) — but most of the growth from the original 31 is the
  `beam4pm_pro` commercial/RevOps/compliance domain (billing, entitlement,
  tenant, procurement, renewal, support, and security/audit-evidence types
  such as `billing_account`, `entitlement_grant`, `tenant_resource_quota`,
  `renewal_risk`, `vulnerability_scan_evidence`). See
  `docs/reference/beam4pm_types_reference.md` (itself ggen-generated) for the
  full, exact field-level reference of all 981.
- Four projections: Erlang, Elixir, Gleam (`gleam/`, with two
  disclosed type divergences noted in its generated comments), and Ash
  (`lib/beam4pm_ash/resources/` — 647 `Ash.Resource` modules, one file per
  resource — manufactured by a second, Elixir-native engine: the
  `ggen_igniter` hex package via
  `scripts/igniter_sync.sh`; its manifest probe renders byte-identical to the
  Rust ggen output).
- Each type is a data structure plus a validating constructor
  (`new_<type>/1` in Erlang, the equivalent in Elixir/Gleam) that checks
  required fields are present and returns `{ok, Record}` or `{error,
  {missing_field, Field}}`. A reflection manifest (`beam4pm_types_manifest`/
  `BeamPM.Types.Manifest`) lists every admitted record and its field names. A
  generated JSON Schema (`schema/beam4pm_types.schema.json`)
  documents the wire shape of every type.
- First real process-mining behavior: generated codecs
  (`beam4pm_codec`/`BeamPM.Codec` — map/JSON in both directions) and
  discovery/conformance (`beam4pm_discovery`/`BeamPM.Discovery` and the
  Gleam `beam4pm/discovery` — `traces_from_events/2`, `dfg_from_traces/1`,
  `conformance/2`). No alignment search, no Petri-net replay.
  `conformance_result.precision` IS computed in all three projections — real
  ETC (escaping-edges) precision via `beam4pm_precision:etc_precision/2,3`
  (`src/beam4pm_precision.erl`, `lib/beam4pm_precision.ex`), called from
  `src/beam4pm_discovery.erl:243`, and via Gleam's `beam4pm/precision`
  (`gleam/src/beam4pm/precision.gleam`), called from
  `gleam/src/beam4pm/discovery.gleam:149`.
- Cross-language identity is proven for THREE directions:
  `bash scripts/roundtrip_check.sh` round-trips every admitted record type × full/minimal
  variants over the JSON wire between Erlang and Elixir in both directions,
  and verifies the same Erlang-written samples through the Ash/`BeamPM.Codec`
  path a third way (Ash's identity relation is `DateTime.compare == :eq` for
  datetime fields, not byte identity; the synthetic `:id` primary key is the
  one disclosed Ash-only attribute). Gleam has no codec leg yet.
- `bash playground/playground.sh` runs the fresh-user workflow end to end
  from a clean `git clone --recurse-submodules` — manufacture, all three test
  suites, real discovery demos in Erlang/Elixir/Gleam, and the roundtrip
  proof. Gate-by-gate standing:
  [`docs/jira/v26.8.29/16-gate-closure-m0-m6.md`](docs/jira/v26.8.29/16-gate-closure-m0-m6.md).
- A DfCM planning crown, `BeamPM.Dfcm` (`lib/beam4pm_dfcm.ex`):
  SELECT-only with deliberately no DO surface (its `allocate_options/2`
  delegates cascade allocation to the external certified `cmca` CLI — see
  the 2026-09-28 admission wave below). It preserves admitted
  alternatives, applies explicit fences, records every exclusion with a
  deterministic receipt and falsifier, and returns either a
  decision-relevant observation request or a SELECT candidate. It composes
  the WS2 FOND/HDDL contracts and is Chicago-qualified against the formal
  HDDL/FOND fixtures (`qualification/fixtures/dfcm/`).
- A replanning ladder, `BeamPM.ReplanRouter`
  (`lib/beam4pm_replan_router.ex`): pure `route/2` checks, in order, the
  stale preimage (`:refuse_stale` — including `policy_digest` enforcement,
  so a plan that does not digest to the admitted policy is never followed)
  and malformed observations (`:refuse_malformed`), then climbs a monotone
  ladder `:close` → `:reobserve` → `:follow_policy` → `:suffix_reuse` →
  `:session_replan` → `:hddl_replan` → `:strategic_recompile`; the rung
  never moves down within an episode. Giving the observation's optional
  `:observed_at` makes a replay produce byte-identical events. Each ladder
  step is linked by `BeamPM.PlanLineage` (`lib/beam4pm_plan_lineage.ex`), a
  sha256 hash chain over plan generations (digests of a canonical JSON
  rendering) whose `verify/1` recomputes the chain and refuses the first
  link that does not match.
- Plan admission is fail-closed by default (2026-09-28 admission wave,
  commits `2a437a7e`, `82438aee`, `0f304857`, `6955b894`, `cf418a79`):
  `config :beam4pm, :admission_mode`
  (`config/config.exs`) defaults to `:required`, so a solved candidate plan
  carrying no admission spec is refused `{:error, {:admission_missing, _}}`
  (`lib/beam4pm_replan_router.ex`); per-call opt-outs are `admission: :skip`,
  `graphlaw_court: false`, and `graphlaw_gate: false`. The graphlaw and
  ferroplan wasm engines run supervised under `BeamPM.EngineSupervisor`
  (`lib/beam4pm_application.ex`) — an engine child is started only when its
  artifact exists and, for graphlaw, the sha256 pin
  (`native/graphlaw/graphlaw_wasm.wasm.sha256`, written by
  `scripts/graphlaw_wasm_fetch.sh`) verifies and the running engine's
  `capabilities` reports the expected `abi_version` (ABI handshake,
  `BeamPM.GraphlawAdmission`, `lib/beam4pm_replan_router.ex:1247-1310`).
- PDDL action models and independent policy admission (same wave):
  `BeamPM.ActionModel.from_pddl/2` (`lib/beam4pm_replan_router.ex:1470`)
  derives a `BeamPM.PlanAdmission` admission spec from PDDL domain/problem
  text — STRIPS + typing, with negated plain atoms admitted as
  `pre_not`/`goal_not` (previously typed `{:error, {:unsupported, _}}`);
  `BeamPM.GraphlawAdmission.admit_policy/3` (`lib/beam4pm_replan_router.ex:1228`)
  checks a ferroplan `UniversalPlan` strong-cyclic via the graphlaw court
  (`{:ok, admitted}` or `{:error, {:refused, refusal}}`); and
  `BeamPM.ReplanRouter.load_policy/4` loads a `UniversalPlan` into state only
  when it digests to the admitted `preimage.policy`, running the graphlaw
  court by default in `:required` mode.
- `BeamPM.Dfcm.allocate_options/2` (`lib/beam4pm_dfcm.ex`) delegates cascade
  allocation to the external certified `cmca` CLI (`autofde cmca allocate`):
  when the CLI is present but refuses (cardinality law, transport failure),
  a refused map with reason `{:cmca_allocate_failed, detail}` is returned —
  the uniform option-preserving fallback is never silently substituted for a
  real refusal. Authority ceiling stays `:select` in every branch.
- `Beam4PM.CastleCapabilityIntake`
  (`lib/beam4pm_castle_capability_intake.ex`): a runtime-readable CASTLE
  capability donor registry admitting EX4PM only as a process-execution
  kernel behind Beam4PM's PROCESS_COORDINATION ownership — authority ceiling
  `:construct`, `dispatch_authority?/1` always `false`, no actuation path.
- Ash-native evidence emission via `AshEx4pm` (26.10.1): the hex dep is in,
  `Ex4pm.Evidence.Store` (the emission sink) auto-starts, and the ingest /
  dedup / refusal / BRCE-gate contracts are test-pinned. The
  generated-resource wiring (`extensions: [AshEx4pm]` + a create-only
  `ex4pm` block per resource) is rendered by the pack template from the
  `bpm:ocelTypeExpr` ladder and lands with the next Ash-leg regeneration
  (currently blocked by a pre-existing ggen_igniter reconciliation
  deadlock — `docs/jira/v26.10.1/RESOLUTIONS.md` R14) — additive to
  beam4pm's own telemetry→OTel→`OcelIngest`/`ReceiptChain` chain, which is
  not rerouted through it.

## Build and test

```sh
git clone --recurse-submodules <this-repo-url>
cd beam4pm
source scripts/env/rust4pm_reactor_env.sh   # points RF2/RF3 tests at the built native oracle binaries
rebar3 eunit   # EUnit tests over the generated Erlang types, manifest, and behavior (3100 at the 424d04c6 verified run; grows with the admitted graph)
mix test       # ExUnit tests over the generated Elixir types, manifest, and behavior (1108 at the 424d04c6 verified run; grows with the admitted graph)
```

`--recurse-submodules` is required: three git submodules manufacture or back
this repo — `vendor/ggen-marketplace` (the pack that manufactures every
record type), `native/ferroplan` (the PDDL planner engine), and
`vendor/rust4pm-powl` (the reference `process_mining` crate the POWL 2.0 wire
types are checked against for field-shape parity). Skipping the
`source scripts/env/rust4pm_reactor_env.sh` step leaves `RF2_ORACLE_BIN`/
`RF3_ORACLE_BIN` unset, which fails 11 of the ExUnit tests loudly with a
`System.EnvError` naming the exact fix — never a silent skip.

**A Rust/cargo toolchain is required**, even though the primary manufacturing
pipeline (ggen/Tera) does not otherwise need Rust: compiling the `ggen_igniter`
hex dependency builds its oxigraph query engine as a Rustler NIF, and the
RF1/RF2/RF3 Chicago tests spawn real Rust subprocess oracles
(`native/rf1-dfg-oracle`, `native/rf2-conformance-oracle`,
`native/rf3-ocel-oracle`) — see `scripts/igniter_sync.sh` and
`playground/playground.sh`'s own step 1/10 toolchain preflight, which checks
for `cargo` (alongside `ggen`, `erlc`, `rebar3`, `elixir`, `mix`, `gleam`) and
fails closed with `BLOCKED: required tool 'cargo' not on PATH` before
attempting the igniter sync, rather than failing deep into the build.

## Regenerating

```sh
ggen sync run
```

(`ggen.lock` is committed at this pin — tracked again by the merge-day
2026-09-27 merge, dba2e267 — so a plain `ggen sync run` uses it; removing it
is only warranted after raising the vendor pin.) This re-runs the ggen pipeline against `ontology.ttl` and the vendored pack,
regenerating every manufactured file (see `scripts/gate_m2_check.sh` for the
authoritative marker-driven definition and current count) from scratch.

## Full doctrine and vision

See [`docs/jira/v26.8.29/README.md`](docs/jira/v26.8.29/README.md) for the
complete v26.8.29 package: architecture and manufacturing doctrine, product
requirements, pricing/packaging, GTM, security/airgap, release gates, and the
`beam4pm_pro` commercial vision.