Skip to content

feat: add the process model and projection packages - #9

Merged
Mearman merged 14 commits into
mainfrom
feat/graph-schema
Oct 10, 2026
Merged

Mearman merged 14 commits into
mainfrom
feat/graph-schema

Conversation

@Mearman

@Mearman Mearman commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

Adds the process model and its projections as two core packages. @exadev/process-graph-schema holds the typed identifier spaces, defineModel, validate, a Zod schema and parseModel loader for the open runtime shape, and the additions below. @exadev/process-graph-projection holds hand-offs, flowchart, swimlane, state machine and sequence diagram.

The supplied reference model is split into modules with behaviour unchanged (the lint rules of this repository forced mechanical style changes, such as T[] for Array<T> and OpenIds as an alias of IdSpace). The order example and the compile-fail blocks are test files, so each package's typecheck fails when an expected error stops being one.

Additions to the model, each its own commit: source binding on activities, artefacts (consumes, produces, inputsOf, outputsOf), a trilean PredicateNode as a transition's condition, affects on activities, an overlay for run state kept apart from the model, and per-element notation extensions. Projection follow-ups: state machine scoped by affects, a swimlane lane for every declared actor, a loss list on every projection result, and authored fragments drawn in sequence diagrams.

trilean-regex is added to minimumReleaseAgeExclude beside trilean: trilean 1.7.2 depends on a trilean-regex release newer than the age gate, and both are ExaDev packages.

Inverse mappings are not part of this change.

The process model as typed identifier spaces (participant, actor, entity, event, action, element,
transition, fragment), declarations and references kept apart, defineModel with compile-time
reference checking, and a runtime validate for what the types cannot state.

The compile-fail checks run as unit tests, so the package typecheck fails when an expected error
stops being one.
The reference projections of the process model: hand-offs, flowchart, swimlane, state machine and
sequence diagram, each a pure function of the model plus the extra input its notation needs.

The order process lives in test support and is asserted in every notation, so an example is never
exported from the library entry point.
The open shape of a model, with plain-string identifiers and every object strict, so a loaded
document with a misspelt field is rejected rather than silently stripped. A type-level test pins
the inferred type to exactly Model<OpenIds>.

parseModel checks the shape first, reporting each problem by JSON pointer, then runs validate and
surfaces its issues in the same error.
An activity may carry a source-qualified identifier such as github:org/repo#12, so a model built
from an external tracker keeps each element's identity in that tracker. validate rejects two
activities sharing one source with the duplicate-source issue.
A new artefact identifier space, ArtefactDef with an optional deliverable flag, and per-activity
consumes and produces lists typed against it, so an undeclared artefact reference is a compile
error like every other space.

validate reports unknown artefact references and an artefact produced by more than one activity.
inputsOf lists the artefacts nothing produces and outputsOf those flagged deliverable.
A transition may carry an evaluable condition beside its human-readable guard, typed as trilean's
PredicateNode so a decision can resolve to true, false or unknown. The open schema embeds
trilean's own schema, so a malformed condition is located by JSON pointer when a model is loaded.

trilean-regex, a dependency of trilean published by the same organisation, joins the install-age
exclusions with the other own packages.
An activity may list the entities whose lifecycle it changes. The list is typed to the entity
space only, so naming a role or a system is a compile error, and validate reports the same
mistake in a loaded model as affects-not-entity.
An Overlay maps element identifiers to done, open or unknown, with a Zod schema whose inferred
type is pinned to Overlay<OpenIds> and a parseOverlay loader that reports problems by JSON
pointer. Run state stays out of the model, the same rule as layout.

The JSON pointer encoding is shared with the model loader.
Every element may hold a record of JSON values keyed by notation name, for concepts that have no
meaning in the model such as an activation bar or a history depth. They load through the open
schema unchanged, so a round trip through a view can restore them.
… its subject

toStateMachine now keeps the activities whose affects lists the subject, plus authored states and
pseudo-states, and folds transitions through the rest the way it folds a decision. A model in which
no activity declares affects keeps every activity, so models without that information project as
before.
toSwimlane now emits a lane for each declared role and system in declaration order, empty when
nothing is assigned to it, so a participant that has not acted yet is still visible. An actor a
runtime model names without declaring keeps its lane after the declared ones.
Every projection result now carries a loss list, a discriminated union on kind: positions for the
projection's own notation, notation-only extensions, message elements, authored fragments, the
activities left out of a state machine's subject, and the elements and untaken branches off a
sequence scenario. A kind is reported only when something was dropped.
toSequence now returns items beside the flat messages: each is a message or an authored fragment
wrapping the scenario's messages that arrive at its body, with the operands the scenario takes,
nested where one fragment's messages lie inside another's operand. A fragment that cannot be drawn
without reordering the scenario is left out and reported as lost, never approximated.
handoffs built the same element-to-actor map the other projections take from actorMap.
@Mearman
Mearman marked this pull request as ready for review October 10, 2026 09:14
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-10-10T09:28:24.135482Z 35f6f23 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mearman
Mearman merged commit 0dc84af into main Oct 10, 2026
14 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.1.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant