Releases: BESSER-PEARL/BESSER
v7.4.1
Patch release: internal cleanup — drop the legacy packages/webapp and rename packages/webapp2 to packages/webapp in the Web Modeling Editor frontend. No user-visible behavior changes, no API changes, no metamodel changes — this is a tidy-up that removes dead code and restores the canonical package name.
Highlights
- Frontend monorepo simplification. The legacy Webpack + Bootstrap
packages/webapppackage — kept on disk "for reference only" since the v7 redesign — is now removed. The active React + Vite + Radix UI app that previously lived underpackages/webapp2is renamed topackages/webappso the canonical workspace name reflects what users actually run. Build artefacts now land inbuild/webapp/instead ofbuild/webapp2/; the standalonepackages/serverreads from the new path directly (the legacy fallback was deleted). - Documentation sweep. Every reference to
webapp2across both repositories is nowwebapp— frontendREADME.md,CLAUDE.md,CONTRIBUTING.md; the backenddocs/source/contributing/RSTs; and 15 frontend Sphinx RSTs (overview/,contributing/,editor/,reference/,webapp/). Stale "this package is deprecated and will be removed" warnings are gone too. - Documentation polish (separate from the rename). Tightened the backend's
README.md,CONTRIBUTING.md,DEVELOPMENT_SETUP.md, andCLAUDE.mdin three small ways: the repository URL is now the canonical Title-CaseBESSER-Web-Modeling-Editor(GitHub still redirects the old all-caps form, but the new form is what we ship); the Node version requirement in the backendCONTRIBUTING.mdis nowNode.js 20+to match the frontend repo's CI matrix; anddocker-compose(Compose v1 syntax) is replaced with the v2 formdocker composein setup instructions.
Compatibility
- No public API change. The published
@besser/wmenpm package (the editor) is untouched; only the internal monorepo workspace name changed. - No metamodel, generator, or backend API change.
- Anyone who scripted
npm run *:webapp2against this monorepo will need to switch tonpm run *:webapp.npm run dev,npm run build,npm run test, andnpm run lintcontinue to work unchanged — they were already aliases that covered both names.
Testing
- Frontend:
npm run buildproducesbuild/webapp/andbuild/server/cleanly under the renamed workspace. - Frontend: 55 perspective unit tests (
project.test.ts,HiddenPerspectivesBanner.test.tsx,ProjectSettingsPanel.test.tsx,WorkspaceSidebar.test.tsx) green. - Backend: no Python code changed; the existing test suite still applies.
v7.4.0
This release introduces a new OCL utility package under besser.BUML.metamodel.ocl (chain, clone, predicates, substitute, walk) and a new OCL normalization subsystem under besser.BUML.notations.ocl.normalization that rewrites parsed constraints into a canonical CNF/iterator-fused form. The Web Modeling Editor gains per-project modeling perspectives (filter the workspace to the diagram families a project actually uses, with quick-select presets and a recovery banner when hidden perspectives still hold content), a substantial agent configuration rewrite, and a number of editor polish fixes. bocl is bumped to 1.0.1 to pick up the matching parser-side fixes.
New Features and Improvements
OCL Utility Package (besser.BUML.metamodel.ocl)
- Added
walk— post-order traversal helper that skips structuralInfixOperatormarkers and surfaces only AST nodes. - Added
clone— typed AST cloner that preserves shared metamodel references (Property, InfixOperator) while deep-copying the expression tree, so rewrite rules can mutate without touching the source. - Added
substitute— capture-avoiding substitution with an explicitScopeStack(push/pop in try/finally), correct under nested iterators and shadowed iterator variables. - Added
chain— extracts the property-call chain rooted at a navigation expression, surfacing the navigation path consumers need for downstream analysis. - Added
predicates— composable predicate set (is_op,is_and,is_implies,is_xor,is_isempty,is_loop, …) for matching nodes in rewrite rules and external analyzers.
OCL Normalization Subsystem (besser.BUML.notations.ocl.normalization)
- Added a fixed-iteration rewrite engine (
normalize.normalize) that drives a deterministic, ordered rule pipeline to a fixpoint, with a developer-bugmax_iterationsguard against non-terminating rules. - Added six rule modules covering the normalization tactics:
boolean(NNF / De Morgan / double-negation elimination),cnf(implies-elimination, if-bool-elim, distribute-or-over-and),collection(size/isEmpty / notEmpty rewrites),iterator(select/forall/exists fusion),multiplicity(multiplicity-aware optimizations),all_instances(allInstances rewrites). - Added
pretty_printerfor human-readable round-tripping of OCL ASTs back to source form. - Added
api.parse_oclas the single new public entry point that wraps the existing ANTLR parser and surfaces aggregatedBOCLSyntaxErrorinstead of raising on the first error. - Added
wrapping_visitorso external callers can catch parse-shaped errors uniformly across the visitor stack. - Narrowed the if-to-boolean rewrite so it only fires on if-expressions whose branches are boolean-typed (preventing accidental rewrites of conditional values), and surfaced unresolved-property errors as
BOCLSyntaxErrorinstead of bareException.
Web Modeling Editor — Modeling Perspectives
- Added per-project modeling perspectives: each project carries a per-diagram visibility map under
BesserProject.settings.perspectivesthat filters the workspace sidebar, mobile navigation, and command palette in lockstep. Hiding a perspective removes it from every switch surface but preserves its diagrams, so toggling it back on restores the workspace state. Project schema bumped from v3 to v4 with an automatic migration that preserves any pre-existing user choices and defaults missing keys to enabled. - Added quick presets in Project Settings — Data Modeler, Agent Developer, Full Application, Quantum, Show All — that flip the per-diagram toggles together for common project shapes. Individual per-diagram toggles remain available below the presets for fine-grained control.
- Added a last-enabled guard: the only remaining enabled perspective cannot be toggled off (the workspace would have nothing to show). Disabling the perspective whose diagram is currently active auto-switches the editor to the first still-enabled type, so the canvas never lands on a hidden diagram.
- Added a hidden-perspectives recovery banner at the top of the workspace that appears whenever the project still references a hidden perspective (either because that perspective's diagrams hold content, or because another diagram cross-references one of them). The banner offers one-click re-enable and renders on every route, including Project Settings itself, so users can recover the moment they realize a toggle was a mistake.
Web Modeling Editor — Agent Configuration
-
Rewrote the Agent Configuration panel for usability: clearer grouping of platform / intent-recognition / LLM provider settings on the agent diagram, refined personalization flow, and tighter agent-variant lifecycle. Agent runtime config continues to live on the agent diagram itself (single source of truth introduced in v7.3.0); no storage changes required for existing projects.
-
Fixed a class-diagram bug where toggling Abstract or Enumeration off left the stereotype label and italic styling on the element; the toggle now clears
stereotype,italic, andunderlineon the underlyingUMLClassinstance.
v7.3.0
This release introduces a new UserDiagram for describing the different end-user profiles of apps, the Agent Personalization workflow to create variations of the same agent for each user profile, and a standalone chatbot deploy target on the existing GitHub deploy flow. It also tightens the deploy export so diagrams.json written into deployed repos is re-importable through the editor, and gates the new recommendation endpoints behind GitHub OAuth so the BESSER server's OpenAI quota cannot be drained anonymously.
New Features and Improvements
User Diagram
- Added UserDiagram as a first-class diagram type for describing the different user profiles of created apps, capturing personal information, language profile, competences, accessibility constraints, abilities, and cultural dimensions in the same metamodel space as the rest of B-UML.
- Shipped an OCL constraint set (
pi_age_range,skill_name_not_empty,education_required_fields,disability_description_not_empty) declared inconstants/user_buml_model.pyand evaluated by the existingcheck_ocl_constraintpipeline. - Extended the validation router so the same
/validate-diagramendpoint covers UserDiagram payloads alongside the existing diagram types. - Added a dedicated palette in the Web Modeling Editor (
UserModelName,UserModelAttribute,UserModelIcon). - The attribute-edit panel now supports enumeration values with case-insensitive enum lookup.
Agent Personalization Pipeline
- Based on a given agent model, user model, and agent profile (defining user-specific customizations), a personalized model can be generated, reflecting the customizations.
- The
BAFGeneratorcan now ingest multiple agent models with a user-profile-to-agent-model mapping and generate an agent that provides a personalized experience based on the available profiles.
Standalone Chatbot Deploy
- Extended
POST /github/deploy-webappto accept adeploy_config.targetof"webapp"or"chatbot"(the frontend translates its"agent"→"chatbot"at the wire boundary).
Web Modeling Editor
- Added the agent-personalization workflow with
AgentConfigurationPanel(absorbing the previous two personalization panels) and an agent-variant management UI on the agent diagram. - Added the Deploy → "Publish to Render" agent target so users can deploy a personalized chatbot directly from the editor.
- Added v2
LocalStorageRepositorymigrations forbesser_systemConfigand the legacyagentConfigkey. - Migrated
useGitHubRepo.createRepotoapiClient.postwithX-GitHub-Sessionforwarded;DeployWebappResponseis hoisted at module scope and thedeployment_urls/is_first_deployfallback lives in a singletoGitHubRepoResultmapper. - Added a real UI-driven Playwright spec at
tests/e2e/github-deploy.spec.tsthat drives the production Deploy menu and asserts the captured request body carriesprojectExport.version === "2.0.0"and a non-emptyproject.diagramsmap. - Object diagram now prefers the
classNamelabel for user-model elements. - Late additions on top of the submodule bump: agent-diagram topbar collapse fix, agent-config mapping-collision warning on Save/Apply, transform timeout raised to 10min with surfaced
TimeoutError, and ProjectHubDialog import-area accessibility/UX improvements.
B-UML Metamodel
- Fixed
Object._validate_object_completenessso a child class that only inherits attributes is still flagged when no slot values are provided. The check now callsclassifier.attributesandclassifier.inherited_attributes()directly (instead of guarding withhasattr/getattrdefaults that masked real type bugs).
Testing
- Backend full
pytestsuite: 771 passed, 5 skipped, 3 xfailed. - New unit tests cover
user_profile_utils,agent_config_recommendation_utils, andagent_config_manual_mapping_utils. - New behavioral integration tests cover
/recommend-agent-config-mapping,/recommend-agent-config-llm, and/deploy-webappwithdeploy_target="agent". - Frontend
vitest: 23/23 onshared/utils/__tests__/projectExportUtils.test.ts. - Added
.github/codeql/codeql-config.ymlexcludingpy/clear-text-storage-sensitive-data: the rule fires on thef.write(render_config)calls in the deploy paths becauserender.yamlreferences env-var KEY names (no password VALUES are written).
Frontend pair
Frontend submodule moves to BESSER-PEARL/BESSER-WEB-MODELING-EDITOR develop HEAD. Matching frontend release: BESSER-PEARL/BESSER-Web-Modeling-Editor#113.
v7.2.0
Minor release: ER notation support for class diagrams + one-to-many REST endpoints. Adds a display-only ER (Chen) rendering flavor for class diagrams in the Web Modeling Editor and closes a longstanding gap in the backend REST API generator where one-to-many relationships had no traversal endpoints. No metamodel or public API changes — ER is a client-side rendering flavor, and the REST endpoint work is additive.
Highlights
-
ER (Chen) notation for class diagrams (#508, WME PR #108): the Web Modeling Editor now supports an ER rendering flavor alongside the default UML notation, selectable from the Project Settings panel under Display. The setting is persisted in
localStorageunderbesser-standalone-settings.classNotationand is rendering-only — the underlying model and its serialized multiplicities stay in UML form, so toggling back to UML is lossless. In ER mode, plain binary associations (bidirectional, unidirectional, aggregation, composition) are drawn with a named diamond at the midpoint of the line; inheritance, realization, OCL link, and dependency keep their UML rendering (explicit allow-list rather than an exclusion list, so new relationship types don't silently inherit the diamond). Multiplicities display in the Chen(min,max)form ((1,1),(0,N),(1,N)) while remaining stored as UML ranges; the association-update popover accepts either syntax as input and normalizes(0,N)/(1,1)to0..*/1..1on save. Class and abstract-class classifiers drop the methods compartment (ER has no operations concept); enumerations and interfaces are explicitly excluded. Attributes marked withis_idrender underlined. The toggle repaints the canvas live via the existingsettingsService.onSettingsChangesubscription inscenes/application.tsx. Shipped with 15 unit tests inmultiplicity.test.tscovering theparseMultiplicity/toERCardinality/erCardinalityToUMLhelpers (including the round-trip invariant for canonical inputs) and a Playwright suite intests/e2e/er-notation.spec.tscovering the radio-group toggle, localStorage persistence, and reload survival. -
One-to-many relationship GET endpoints in the REST API generator (PR #509): the FastAPI backend generator was only emitting relationship-traversal endpoints for many-to-many associations, which meant generated BAL methods that walked one-to-many navigations could not actually resolve the target objects at runtime.
backend_fast_api_template.py.j2now emits a matchingGET /<class>/{id}/<relationship>/endpoint for every one-to-many association, mirroring the shape of the existing many-to-many block — 404 on missing parent, SQLAlchemy-filtered child query on the foreign-key column, response payload shaped as{<class>_id, <rel>_count, <rel>}. The endpoint is tagged"<Class> Relationships"so it groups correctly in the generated OpenAPI docs.
Frontend submodule bump
The frontend submodule moves from 279c8f8 to b8b522e — all 12 commits are part of the ER-notation feature branch (feature/er-notation-508). No unrelated commits piggy-back on this pointer move.
Testing
Backend: full suite passes against v7.1.7 baseline — the REST API generator change is covered by template-rendering tests (no new regressions). Frontend: 15 unit tests in multiplicity.test.ts plus the er-notation.spec.ts Playwright suite are additive; existing UML rendering tests continue to pass unchanged.
v7.1.7
Version 7.1.7
Patch release: OCL parser fixes + IMG2UML merge-into-existing-model. Closes #198, #202, and #338. No metamodel or public API changes — the OCL work is a grammar fix plus a diagnostics layer, and the IMG2UML change adds an optional parameter while preserving the original behaviour when the active diagram is empty.
Highlights
- OCL accepts attributes named
size(closes #198):sizeis a reserved lexer keyword for the OCL->size()/.size()collection operation, so any domain model with an attribute literally namedsizefailed to parse withmismatched input '>' expecting '('— the lexer tokenized the attribute name asSIZEand the parser insisted onLPAREN RPARENafter it. The reporter blamed inheritance because their repro hadsizeon a parent class, but the bug fired identically on a direct attribute. Grammar fix:expression DOT SIZE #dotSizeNavigationadded as a fallback rule below the existingDOT SIZE LPAREN RPAREN. ANTLR's longest-match keeps.size()winning when parens follow, socollection->size()andstring.size()still parse unchanged. The visitor gainsvisitDotSizeNavigationthat resolvessizevia the same property-lookup path asvisitDotNavigation. Seven regression tests intests/BUML/metamodel/ocl/test_size_attribute.py. - OCL parser emits actionable error messages (closes #202): the raw ANTLR diagnostics (
mismatched input 'then' expecting <EOF>,missing ')' at '<EOF>') exposed internal parser state and used token names that mean little to someone writing an OCL constraint. The worst example from the issue — forgetting theifbeforethen ... else ...— surfaced asError: pop from empty list, which gives zero hint about what went wrong.besser/BUML/notations/ocl/error_handling.pynow sits on top of ANTLR's error listener and rewrites diagnostics into OCL-level hints:Did you forget the 'if'?,Missing 'endif',Missing closing ')',operand on the right is missing,must start with 'context <ClassName> inv: ...', and so on. When no targeted pattern matches, the raw ANTLR message is kept as a fallback but reformatted into a consistentline N, column M: <msg>shape. Thirteen regression tests intests/BUML/metamodel/ocl/test_error_messages.pypin every rewrite rule plus positive-parse sanity checks so the translation layer doesn't reject valid OCL. - IMG2UML extends an existing class diagram instead of replacing it (closes #338): when an image is uploaded while the active ClassDiagram already has elements, the image is now merged into the current model — same-name classes are preserved and only new attributes/methods/relationships from the image are appended, new classes are added with their own relationships.
image_to_bumlandimage_to_plantumlgain an optionalexisting_modelparameter; when supplied, a compact textual summary of the current classes, attributes, methods, associations and inheritance is included in the vision prompt with explicit merge rules so the LLM returns a single merged PlantUML chunk./get-json-model-from-imagecarries an optionalexisting_modelform field with the current diagram JSON, converted viaprocess_class_diagramand forwarded down. The frontend submodule only sends the active ClassDiagram when it is non-empty, so empty-diagram imports keep the original "replace" behaviour.
Testing
Twenty new OCL tests (seven for the size keyword fix, thirteen for the error-message rewrites) cover every targeted pattern plus positive-parse guards. Full suite: 712 passed, 5 skipped, 3 xfailed — no regressions against v7.1.6.
v7.1.6
Version 7.1.6
Minor release: identifier story overhaul + more permissive PlantUML importer. Closes #230, #225, #108, #236 and completes the is_id work from #478 / #486. Frontend submodule advances twice to expose the two new attribute checkboxes.
Highlights
- New
Property.is_external_id(closes #230, #225, #108): B-UML now distinguishes the internal surrogate PK (is_id) from user-facing identifiers (is_external_id). Composite keys supported. Flag round-trips through metamodel, JSON converters, and code builder. SQLAlchemy emitsunique=Trueon non-PK external ids (subsumes #108's UNIQUE ask). Django emitsunique=Trueand — crucially for #225 — uses external ids in__str__so ForeignKey dropdowns showisbn/first_name - last_nameinstead of the PK. is_idpropagation completed (#478): PR #486 landed the metamodel + converters but deferred the builder, generators, and editor. Finished here:domain_model_to_codeemitsis_id=True, Django template emitsprimary_key=True, editor gains an ID checkbox (SQLAlchemy already worked).- PlantUML importer permissiveness (closes #236): grammar now accepts single-dash
-associations,integer/booleantype aliases, and trailing</>direction hints on labels. Lexer/parser regenerated with ANTLR 4.13.2. - Django template whitespace fix: pre-existing bug where the attribute for-loop stripped every newline — rendered
models.pywas invalid Python. Regression test compiles the output. - Editor UI (submodule c4252a6 → b5102c0): two new attribute-popup checkboxes (ID, External ID),
{id}/{external id}markers in the display name, plusc50f6dc(attribute/method reorder — piggybacked ondevelop).
Testing
11 new tests: metamodel setter validation, JSON↔BUML round-trip, code-builder exec round-trip, SQLAlchemy schema introspection + real IntegrityError on duplicate external-id, Django field emission + __str__ variants + compile() sanity, and 5 PlantUML grammar regressions. Full suite: 692 passed, 5 skipped, 3 xfailed.
v7.1.5
Version 7.1.5
Patch release: the DB Agent template now generates without an internal server error. Backend-only fix — no metamodel, generator, or public API contract changes. The frontend submodule pointer is unchanged.
Highlights
- DB Agent template generation no longer fails with
NameError: name 'ReceiveTextEvent' is not defined: the shippeddbagent.jsontemplate has an event-only transition ("event": "ReceiveTextEvent"with no conditions), whichagent_model_builder.agent_model_to_codeemits asinitial.when_event(ReceiveTextEvent()).go_to(db_reply). The generated module's import block pulled inAgent, AgentReply, LLMReply, RAGReply, DBReplyand the LLM classes, but none of the*Eventclasses.generate_agent_filesingeneration_router.pythenexec_module-ed the generated file and raised, which the frontend surfaced as a 500 on/besser_api/generate-output. The other four shipped templates (faqragagent,greetingagent,gymagent,libraryagent) hid the bug because they use intent-matcher transitions and the builder emits those aswhen_intent_matched(intent).go_to(...)without ever referencing the event class directly. - Fix:
besser/utilities/buml_code_builder/agent_model_builder.pynow addsReceiveTextEvent,ReceiveFileEvent,ReceiveJSONEvent,ReceiveMessageEvent,WildcardEvent, andDummyEventto thefrom besser.BUML.metamodel.state_machine.agent import ...line it writes into the generatedagent_model.py. All six are already exported bybesser.BUML.metamodel.state_machine.agent— this change only affects generated code, not runtime behavior of the builder itself. - Regression coverage: all five shipped agent templates (
dbagent,faqragagent,greetingagent,gymagent,libraryagent) were round-tripped throughprocess_agent_diagram→generate_agent_filesand each produces a validagent_output.zipcontaining a syntactically validagent_model.pyand theBAFGeneratoroutput bundle.
v7.1.4 — accept XLSX uploads in the Project Hub spreadsheet flow
Patch release: the "From Spreadsheet" project creation flow now accepts XLSX workbooks as advertised. Backend-only fix — no metamodel, generator, or public API contract changes. The frontend submodule pointer is unchanged.
Highlights
-
XLSX uploads in
/besser_api/csv-to-domain-modelno longer fail with "Unsupported file type '.xlsx'" (#501). The Project Hub "From Spreadsheet" dialog already exposedaccept=".csv,.xlsx,.xls,..."on its file input and the copy promised "Auto-generate a class diagram from CSV/XLSX files", but the backend's_validate_uploadwhitelisted only{".csv"}and rejected everything else with a 415.conversion_router.pynow carries anALLOWED_SPREADSHEET_EXTENSIONS = {".csv", ".xlsx"}set, validates.xlsxcontent by checking the ZIP magic bytes (PK\x03\x04), and converts each uploaded workbook's first worksheet to a UTF-8 CSV viaopenpyxlinside the request's temp directory before handing the resulting path list to the existingcsv_to_domain_modelreverse engineer.csv_reverse.pyitself is unchanged — the xlsx-to-csv normalization happens entirely in the endpoint. -
New optional backend dependency:
openpyxl >= 3.1.0added tobesser/utilities/web_modeling_editor/backend/requirements.txt(not the top-levelrequirements.txt— this only matters for the editor backend). The import is lazy inside the helper, so the rest of the backend stays importable when the package is missing; if a user uploads XLSX without openpyxl installed they get a clear 500 with installation instructions instead of a traceback. -
Legacy
.xls(BIFF) is deliberately not supported. Reading.xlswould require the deprecatedxlrdpackage (upstream dropped.xlsxsupport in 2.0 and warns against use for new work). Users who upload.xlsget the same clear 415 as before, listing.csv, .xlsxas the allowed extensions. -
Regression coverage in
tests/utilities/web_modeling_editor/backend/test_spreadsheet_import.py: CSV upload still succeeds, XLSX upload succeeds and produces aClassDiagram, unsupported extensions return 415 with both allowed extensions named in the error, and malformed XLSX (bad magic bytes) returns 400 before reaching openpyxl.
v7.1.3
Patch release.
Highlights
- Standalone agent ZIP now contains the full BAF project.
BAFGeneratorwas being constructed without anoutput_dir, so it wrote to<backend-CWD>/outputinstead of the request's temp dir. The downstream zipper walked the (empty) temp dir and shipped anagent_output.zipthat only held the rawagent_model.py. Both constructor branches in_handle_agent_generationnow pinoutput_dirto the request temp dir. WebApp-embedded agent flow was unaffected. - Modeling agent can now link new Object Diagram instances to their class.
add_objectdropped the referenceclassIdentirely, so the update panel's "class:" dropdown always looked empty.ObjectDiagramModifierandObjectDiagramConverternow carryclassId/attributeIdthrough to the created elements. - No more
author2: Author : Authordouble rendering. After wiringclassIdthrough, the component started appending" : ClassName"on top of a name that already contained it..namenow holds only the bare instance name whenclassIdis set. - Frontend submodule bump also pulls in: drag perf fix (fractional deltas),
DeployResultDialogcopy refresh, unified external URL handling, agent diagram title-uniqueness, more robust object removal.
Full release notes: docs/source/releases/v7/v7.1.3.rst
v7.1.2
Patch release: adds multi-agent support to the Full Web App generator and hardens the GitHub → Render deployment pipeline. No metamodel or API changes.
Highlights
- Multi-agent Full Web App: projects with multiple
AgentDiagrams now generate one agent per diagram underagents/<slug>/. GUIAgentComponents route per-component via a newVITE_AGENT_URLSJSON map.docker-compose.ymlandrender.yamlemit one service per agent. - Stable Render service names: the generator reuses the existing suffix from the repo's
render.yamlon redeploy instead of minting a fresh one — no more zombie services on every push. - WebSocket auto-reconnect: the generated React
AgentComponentretries on failure with backoff (2s → 30s, ~26 min budget), so cold-starting free-tier agents connect transparently without a manual refresh. - Agent-name uniqueness: adding a template that would collide auto-suffixes (
"Library Agent"→"Library Agent 2"); manual renames to a duplicate are hard-blocked.
Bug Fixes
- Underscore → dash hostname normalization: Render silently rewrites
_to-in subdomains. Bothapp_nameand agent slugs are now converted up-front so the URLs baked into.env.productionactually resolve. - 40-character hostname cap: Render truncates longer service names at dash boundaries, dropping our suffix. The new
_fit_service_name()helper falls back to a deterministicbesser-<12 hex>form (stable across redeploys) when the readable name would overflow. - Agent dropdown enumerates every
AgentDiagram:getAgentOptions()used to return only the GUI diagram's per-diagram reference, collapsing multi-agent projects to one selectable agent. - Template add preserves auto-suffixed titles:
TemplateLibraryDialogwas re-applying the template's original title afteraddDiagram()returned a unique title, silently undoing the uniqueness resolution. Fixed. - Deploy result dialog now distinguishes first deploy (create-blueprint link) from redeploy (direct live-app link + Manual Sync guidance).