TramAI - governed AI workflows for Java and Kotlin

Contributor Change Guides

TramAI's structure is enforced, not just documented. Every extension point has a contract test that fails the build when you drift from it, so a change is only "done" when the gates that own it pass.

Each guide below names four things:

  1. the exact extension point — the SPI, interface, or builder you implement;
  2. the files that must change — including the machine-readable registries;
  3. the mandatory contract tests — the TCKs and architecture guards that act as independent oracles;
  4. the verification commands — the gates you run before requesting review.

Every guide also ends with a trap list: what fails CI when you skip a step.

The Guides

ChangeGuideKey contract
New provider adapter moduleAdding a ProviderProviderTck + ProviderTckEnrollmentArchitectureTest
New persistence store implementationAdding a Storeshared store TCKs + *EnrollmentArchitectureTest
New workflow step (built-in or external)Adding a Workflow Stepstep tests + definition-digest golden + cancellation scanner
New approval state or transitionAdding an Approval StateApprovalStoreTck + ApprovalContinuationStoreTck + lifecycle-model property tests
New runtime eventAdding an EventRuntimeEventCatalogueArchitectureTest (ASM + source scan)
Change structured-output constraintsChanging Structured-Output ConstraintsStructuredOutputContractTck + ContractEvolutionTest

How The Guides Stay Honest

Each guide is written against the 0.6.0 source tree with verified path:line references. The contract tests it names are independent oracles: they are deliberately not derived from the implementation, so they fail loudly on drift.

If a guide's facts no longer match the code, the codebase moved. Update the guide in the same pull request that moves the contract, or the next contributor following it wastes a review round.

Authority For Module Metadata

Never hand-write module classification into documentation. The single source of truth is in the TramAI repository:

FileWhat it owns
config/quality/module-catalog.ymlModule path, description, maturity, apiStability, layer, publishability, rationale, and the shared entryDefaults anchors (&provider, &core, &runtime, &framework, &capability, &security, &persistence, &operations, &internal, &publishedTesting)
config/quality/module-boundaries.ymlAllowed layer edges, forbidden edges (published → internal, published → applications-examples, published → excluded), self-edges, and cycles

./gradlew verify060Architecture verifies the catalog against the actual Gradle projects, the published artifact set, and BOM membership. Adding a module without a catalog entry — or with a classification that does not match reality — fails that gate.

Where To Start Reading

These guides cover repository-level changes. If you are consuming TramAI rather than extending the repository, start with the extension guides instead — they cover the same surfaces from the outside:

Two deep dives give the context these guides assume:

  • Module Architecture — the 0.6.0 ten-layer topology, the machine-readable authorities, and the boundary rules
  • Quality Gates — how the gates named in these guides are composed, including the coverage and mutation ratchets

Non-Negotiable Rules

These apply to every guide in this section:

  • Never weaken a TCK or architecture guard to make your change pass. The test is the contract.
  • Never edit the analyzer baseline (config/quality/0.6.0-baseline.json) in the same pull request as a behaviour change.
  • Never route a new extension around the catalog. Enrolment is architecture-enforced.
  • CancellationException is preserved and propagated on every path. Use dev.tramai.core.coroutines.rethrowIfCancellation() in catch (e: Exception) blocks.