Version 7.6.0¶
This release lands OCL preconditions and postconditions end-to-end, from
the BUML metamodel through the Web Modeling Editor’s class-diagram converter,
validator, and canvas. Method.pre and Method.post are now first-class
list fields on Method, the OCL textbox in the editor speaks the canonical
BOCL form (context X (inv|pre|post) [name]: body), and the validator walks
every method’s pre/post lists in addition to the domain model’s invariants —
so a typo’d pre constraint surfaces with a [Class::method kind name] label
that points at the offending box. OCLConstraint exposes the parsed
ast separately from the source-text expression, giving downstream tools
(Lean encoder, SQL CHECK generators, IDE tooling) a stable API surface.
Alongside, the editor’s template library gains a Full Project tab with
multi-diagram bundles, project creation gains modeling-perspective
selection, and a number of OCL hardening and codegen safety fixes land.
New Features and Improvements¶
OCL Metamodel — Pre/Post and AST/Source Split
Added
Method.preandMethod.postas first-class list fields onMethodwith name-uniqueness validated via property setters, plusadd_pre/add_posthelpers. Operation contracts no longer rely on naming-convention scraping to be discovered — they are anchored on theMethodthey constrain.Tightened
Constraint.expressionfromAnyto strictstr(TypeErroron non-str) and addedOCLConstraint.astexposing the parsedOCLExpression. The constructor enforces thatexpressionarrives parsed; theastsetter refreshes the source-text expression via the pretty-printer. The split gives walkers and analyzers a stable typed entry point while leavingexpressionas the canonical source representation.DomainModel._validate_constraintsnow walks everyMethod.pre/Method.postin addition todomain_model.constraints, so a precondition with a stale or external context is flagged the same way an invariant would be.Documentation:
docs/source/buml_language/model_types/ocl.rstadds a workedadd_pre/add_postexample and a sub-toctree pointing at newparsing.rst,ast.rst, andnormalization.rstsub-pages;api_ocl.rstexpands autodoc to coverclone,parse_ocl,pretty_print,normalize, andBOCLSyntaxError;examples/ocl.rstis rewritten as a runnable end-to-end example.
Web Modeling Editor — OCL Pre/Post Wiring
Added a
parse_constraint_text(text, model)helper that inspects the BOCL header to extract kind / class / optional method / optional name, resolves the class manually, and delegates lex/parse toparse_ocl(...)with an explicitcontext_class(the upstream auto-detect regex doesn’t handle theClass::method(params)form).process_ocl_constraintsnow returns(kind, OCLConstraint, class_name, method_name)routing tuples.The class-diagram processor routes constraints by their parsed kind: invariants land on
domain_model.constraints; preconditions and postconditions land onMethod.pre/Method.post. Method lookup is by the(class, method)name pair and walks the inheritance chain, so a precondition written ascontext Sub::base_method() pre: ...resolves to a method declared on a parent class instead of warn-skipping.The class-diagram converter on the BUML→JSON path emits the full BOCL header on every constraint box (invariant, pre, and post) so editor round-trips preserve kind, target method, name, and description without back-channel metadata. Pre/post emission walks
Method.pre/Method.postdirectly.Added a back-compat shim that transparently lifts body-only JSON files (saved during an intermediate iteration) to the canonical full-text shape on first ingest, then
buml_to_jsonnormalizes them on emit. Legacy projects round-trip cleanly without manual editing.Validator (
services/validators/ocl_checker.py) now walks every class’s methods’ pre/post lists in addition todomain_model.constraints; error labels include the[Class::method kind name]triple so messages point at a specific constraint box instead of “constraint #3”.Auto-generated invariant names are embedded back into
constraint.expressionso the next BUML→JSON→BUML cycle parses out the same name instead of generating a freshcounter_blockidxsuffix.Tests: 17 new tests covering routing, malformed-OCL skip-with-warning, legacy ingest, and full-text round-trip stability.
Web Modeling Editor — OCL Constraint Box (Frontend)
The OCL constraint box renders an italic stereotype badge above the body —
«inv»,«pre» <method-name>,«post» <method-name>— derived from the constraint’s BOCL header, giving a visual cue for the kind without introducing a separate metadata field. When the text doesn’t match the BOCL header regex (empty or malformed), no badge renders.Added an optional
descriptionfield on the constraint popup so users can attach a plain-language explanation that the validator surfaces as the violation reason instead of the raw OCL.The constraint textbox is back to a single full-text field carrying the whole BOCL block (
context X (inv|pre|post) [name]: body). Routing intoMethod.pre/Method.posthappens entirely on the backend by parsing the OCL header tokens — no frontend metadata churn, no risk of body / metadata drift.Added a “Library with OCL” structural-pattern template pre-populated with eleven canonical OCL constraints — invariants on
Book/Library/Authorplus preconditions and postconditions on common operations — so users get a working pre/post example one click away.
OCL — Other Improvements
Added an optional
descriptionfield onConstraintthat threads end-to-end (metamodel, JSON↔BUML converters, validator output, code builder). Inline OCL--comments per constraint are also accepted on ingest, with the inline comment winning if both are present (#499).De-duplicate constraint names across OCL boxes (whether typed by the user or auto-generated) instead of crashing
_process_constraints. The de-dup loop preserves insertion order, keeping the first occurrence and emitting aWarning: duplicate constraint name 'X'…so users can spot the collision in the validator output. Discovered via a 2000-constraint stress test (5 parallel agents exercising invariants, pre/post, multi-block, evaluator, and adversarial inputs).Consolidated the OCL constraint pipeline around a single contract:
constraint.expressioncarries the full canonical OCL text from the moment a constraint is parsed through every storage, transport, validation, and evaluation step. Three reconstruction layers and one mutation hack are gone (_method_signature/_already_full_text/_canonical_invariant_text/_canonical_method_contract_textand the swap-and-restore aroundparser.evaluate()); a narrow_ensure_canonical_expressionlegacy fallback remains for old BUML files (deprecated, removal target 2026-Q4).
Hardening and Code Quality¶
Identifier-injection hardening on BUML codegen:
constraint.nameandmethod.nameno longer flow straight into Python identifier positions on the LHS of assignments. Names likex=1;import os;os.system('id')#(no spaces, no hyphens, passesNamedElement.name’s setter) used to land verbatim in code that getsexec()’d. Every identifier emit site now routes throughbuml_code_builder.common.safe_var_namevia a new_method_var_name(method)shim, replacing five different copies ofmethod.name.split('(')[0].Pre/post boxes preserve their
descriptionon JSON↔BUML round-trip; the BUML→JSON converter’s invariant emit path is mirrored on the method-contract path so the field is no longer silently dropped.Sorted
method_contractsindomain_model_builderso the emitted Python is byte-stable across runs (matches how invariants and other emissions sort).Narrowed the residual
except Exceptionin OCL element processing to(BOCLSyntaxError, ValueError)so programmer errors propagate instead of being swallowed.Dropped defensive
getattr/hasattrguards on metamodel attributes that the metamodel now guarantees (Class.methods,Method.pre,Method.post).Stress-tested the OCL pipeline with 2000 constraints across 5 parallel agents (invariants, pre/post, multi-block, evaluator, adversarial inputs) — surfaced and fixed the duplicate-name crash and the round-trip
description-loss above; the rest of the pipeline survived without regressions.
Web Modeling Editor — Templates and Project Hub¶
Added a Full Project tab to the template library carrying multi-diagram project bundles (class diagram + GUI no-code diagram + agent diagram in one click) — a step beyond the existing single-diagram pattern templates.
Shipped two full-project templates: Library Full Stack (full class diagram + GUI + REST API skeleton) and Personalized Gym Agent (an end-to-end agent project demonstrating the multi-diagram model with a configured agent and supporting data model).
Project creation now offers a modeling-perspective selector so the project starts with the workspace already filtered to the diagram families the user intends to model, reducing the initial-noise problem on a fresh project.
Object diagrams: a referenced class can now seed a generated set of objects and links matching that class’s structure, so a user editing an object diagram doesn’t have to hand-construct every object instance from scratch.
Refactored project-import logic into
shared/servicesso the import pipeline is reusable across the project hub and the GitHub-import path.Workspace: setting up the diagram bridge when loading a project (the editor now wires the diagram-state bridge during project load instead of relying on a downstream component to do it, fixing a class of “diagram opens but feels frozen” bugs).
Renamed the Full Application perspective preset to Full Web Application so the label matches what the perspective actually selects (web frontend + backend + API), with no behavior change.
i18n: removed the German locale stub (it was incomplete and being toggled-on in production produced a half-translated UI).
Web Modeling Editor — Backend Fixes¶
Django generator: re-introduced the
chdir(temp_dir)guard around thedjango-admin startprojectinvocation. The pre-refactorbackend.pywrapped the call inchdir/try-finally; the extracted_generate_djangohelper ingeneration_router.pyhad dropped the guard, so the project got scaffolded in the FastAPI process’s CWD while the harvester walked an emptytemp_dir/<project_name>, surfacing asDjango project generation failed: Output directory is empty. The guard is now scoped to the worker thread and restores CWD infinally.GitHub deploy:
deploy_webapp_to_githubnow branches onhttpx.HTTPStatusErrorand surfaces the actual GitHub API error ("name already exists on this account", expired token, rate limit) instead of letting it fall through to the catch-all 500 handler.401/403pass through;422maps to409 Conflictso the UI can offer rename / overwrite; other4xxpass through;5xxbecomes502 Bad Gateway. The frontend’s deploy popup now shows something the user can act on.
Modeling Assistant — Natural Language to OCL¶
Closes BESSER-PEARL/B-OCL-Interpreter#5. The modeling assistant can now author
OCL constraints from a plain-language description. When the user explicitly asks
for an invariant, precondition, or postcondition ("add a constraint that a
Library always has at least one Book", "the precondition of Account::deposit
is amount > 0", "after deposit the balance must not be negative"), the
agent emits an add_ocl_constraint modification, and the frontend spawns a
constraint box on the canvas linked to the target class via a ClassOCLLink.
Modeling-agent (
BESSER-PEARL/modeling-agent):ClassModificationadds theadd_ocl_constraintaction with optionalchanges.constraint(full BOCL block) andchanges.text(plain-language description). The class-diagram system prompt gains an OCL section listing the four header shapes (inv/pre/post/init) plus five NL→BOCL examples. Emission is gated on the user explicitly asking — the prompt forbids unprompted OCL.Web Modeling Editor frontend:
ClassDiagramModifier.addOclConstraintconsumes the new action and creates aClassOCLConstraintelement +ClassOCLLinkto the anchor class, with the BOCL text in the constraint field and the plain-language description in thedescriptionfield. The rendered box picks up the canonical stereotype badge («inv»/«pre»/«post») introduced earlier in this release.Validation: pre-flight validation (calling
/validate-diagrambefore writing) is a known follow-up — for now, malformed BOCL surfaces post-hoc through theparse_constraint_textvalidator path landed in PR #529.Deploy alongside: this feature requires the matching modeling-agent commit (
c0e47e8onmain) to be live. Use./scripts/deploy.sh agentto roll the modeling-agent container forward at release time.
Documentation¶
OCL: new sub-pages under
buml_language/model_types/ocl/cover parsing, the AST, and normalization — the public surface a tool walking the OCL AST needs.OCL:
ocl_grammar.rstclarifies the.expression(str) /.ast(OCLExpression) split.OCL:
examples/ocl.rstrewritten as a runnable end-to-end example, with the prior invalid-syntax example fixed.OCL:
api_ocl.rstexpands autodoc to coverclone,parse_ocl,pretty_print,normalize,BOCLSyntaxError.