Teaching examples that run, each built from the specification beside it - #1
Teaching examples that run, each built from the specification beside it#1dialexpert wants to merge 19 commits into
Conversation
Every model was imported and compiled on the platform, and the diagnostic read back. Six defects kept eleven of the fourteen from compiling: - stale RestApi and RestApi/GET declarations omitted the Timeout parameter that the engine's inlined body references, so the identifier bound to the type System.Threading.Timeout (CS0119); - a leftover TestCodeAction stub declared a string[] return and returned nothing. The engine emits a method for every declared Code Action, called or not, so the stub failed the whole model (CS0161); - HandleException received #Previous where it needs #PreviousData, leaving the Exception unreachable in the branch that only a failure reaches; - two models read Parameters.config without declaring the parameter; - the Config type of the configuration Flow declared fewer fields than its consumers read: to_email and basic_auth were used but never declared. Its own comment had listed them as intended since the first commit. Node labels are English now. Identifiers are untouched, so sequence flows, associations and the diagram still resolve, and event names — which the event-based gateway matches branches by — are left exactly as they were. Nine of the fourteen models now compile on their own. The remaining five need a companion Flow or a stand configuration that this repository does not ship. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The root README has been English from the start; the pattern guides, the type design chapter and the catalogue were not, which left the publish target unusable for the reader it is published for. Translated with the structure preserved: same headings and levels, same table columns and row order, same code blocks. In CATALOGUE.md every count, model path and reserved-word list is byte-identical to before; only prose and column headers changed. Adds a "Companion Flows" section to the group index. A Flow takes its settings from a separate configuration Flow through a Call Activity (activities://bpmn-mnemo/<libType>/<libName>/<flowName>/#latest) and declares that Flow's shared types as external (types://external/<lib>/<Type>). The indirection is what keeps a model independent of its environment and keeps one declaration of a type instead of a copy per Flow — and it is also why an example that references a companion will not compile until the companion exists in the target library, under the name the reference uses. The table says which example needs which. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4a086a86c
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| environment you import into. Every other example in the table of contents above | ||
| compiles on its own. |
There was a problem hiding this comment.
Document every required companion flow
The standalone-compilation claim is false for at least 07-triggers/http-route-start.bpmn, whose Call Activity targets the environment-only chat-compleation-call flow at lines 46–49, despite this flow being absent from the import table. The ai-completions.bpmn row is also incomplete because that model additionally calls the pinned numeric target activities://bpmn/personal/12/1726/13. Users following these new instructions will still encounter missing-flow compilation failures, so list all required targets or exempt these examples from the claim.
Useful? React with 👍 / 👎.
The table missed two required targets, so the standalone-compilation claim was false where it mattered most — for a reader on a different stand. - `07-triggers/http-route-start.bpmn` reaches `ama_base_agent` and `chat-compleation-call` in the tenant library `AI_Agents_Shared`. It compiled during review only because those flows happened to exist on that stand, which is the accident this table exists to remove. - `08-ai-agents/ai-completions.bpmn` also carries the version-pinned target `activities://bpmn/personal/12/1726/13`, which the mnemonic-only reading of the models did not surface. Both reference forms are now named in the text: the mnemonic one resolves by name and follows `#latest`; the numeric one pins a version, carries no name and resolves only in the environment its identifiers came from. Found by the automated review on this pull request. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 673e06e71d
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <extensionElements> | ||
| <gp:globalParameter name="CodeActionsTypes">["Action","Function"]</gp:globalParameter> | ||
| <gp:globalParameter name="InnerTypes">[{"name":"Config","definition":" public class Config\r\n {\r\n /*логін\r\n пароль\r\nконнешн до бази\r\nнтв-айді\r\nмоде\r\nto\r\nfrom\r\nto_error\r\nfrom_error*/\r\n public string login { get; set; }\r\n public string password { get; set; }\r\n public string db_connection_str { get; set; }\r\n public string value { get; set; }\r\n public int id { get; set; }\r\n }","isNativeDefinition":true},{"name":"ErrorResponse","definition":"{\r\n \"$schema\": \"http://json-schema.org/draft-06/schema#\",\r\n \"$ref\": \"#/definitions/ErrorResponse\",\r\n \"definitions\": {\r\n \"ErrorResponse\": {\r\n \"type\": \"object\",\r\n \"additionalProperties\": true,\r\n \"properties\": {\r\n \"LevelMessage\": {\r\n \"title\": \"The Error level\",\r\n \"type\": \"string\"\r\n },\r\n \"statusCode\": {\r\n \"title\": \"The Error Status Code\",\r\n \"type\": \"integer\"\r\n },\r\n \"ErrNumber\": {\r\n \"title\": \"The Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Message\": {\r\n \"title\": \"The Error Message\",\r\n \"type\": \"string\"\r\n },\r\n \"State\": {\r\n \"title\": \"The Error State\",\r\n \"type\": \"string\"\r\n },\r\n \"HelpLink\": {\r\n \"title\": \"The Help Link\",\r\n \"type\": \"string\"\r\n },\r\n \"errNumberReason\": {\r\n \"title\": \"The initial Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Data\": {\r\n \"title\": \"The Error Data\",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"LevelMessage\": {\r\n \"title\": \"The Error level\",\r\n \"type\": \"string\"\r\n },\r\n \"statusCode\": {\r\n \"title\": \"The Error Status Code\",\r\n \"type\": \"integer\"\r\n },\r\n \"ErrNumber\": {\r\n \"title\": \"The Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Message\": {\r\n \"title\": \"The Error Message\",\r\n \"type\": \"string\"\r\n },\r\n \"State\": {\r\n \"title\": \"The Error State\",\r\n \"type\": \"string\"\r\n },\r\n \"HelpLink\": {\r\n \"title\": \"The Help Link\",\r\n \"type\": \"string\"\r\n },\r\n \"errNumberReason\": {\r\n \"title\": \"The initial Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Data\": {\r\n \"title\": \"The Data Schema\",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"LevelMessage\": {\r\n \"title\": \"The Error level\",\r\n \"type\": \"string\"\r\n },\r\n \"statusCode\": {\r\n \"title\": \"The Error Status Code\",\r\n \"type\": \"integer\"\r\n },\r\n \"ErrNumber\": {\r\n \"title\": \"The Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Message\": {\r\n \"title\": \"The Error Message\",\r\n \"type\": \"string\"\r\n },\r\n \"State\": {\r\n \"title\": \"The Error State\",\r\n \"type\": \"string\"\r\n },\r\n \"HelpLink\": {\r\n \"title\": \"The Help Link\",\r\n \"type\": \"string\"\r\n },\r\n \"errNumberReason\": {\r\n \"title\": \"The initial Error Number\",\r\n \"type\": \"string\"\r\n }\r\n }\r\n },\r\n \"ResolveUrl\": {\r\n \"title\": \"The Resolve Url Link\",\r\n \"type\": \"string\"\r\n }\r\n }\r\n },\r\n \"ResolveUrl\": {\r\n \"title\": \"The Resolve Url Link\",\r\n \"type\": \"string\"\r\n },\r\n \"extraData\": {\r\n \"title\": \"The Error Extra Data \",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"operationDuration\": {\r\n \"title\": \"The Operation Duration\",\r\n \"type\": \"integer\"\r\n }\r\n }\r\n }\r\n },\r\n \"title\": \"ErrorResponse\"\r\n }\r\n }\r\n}","isNativeDefinition":false},{"name":"SystemException","definition":"{\r\n \"$schema\":\"http://natec.tech/simpleschema\",\r\n \"$ref\":\"#/definitions/SystemException\",\r\n \"definitions\":{\r\n \"SystemException\":{\r\n \"type\":\"object\",\r\n \"properties\":{\r\n \"Exception\":{\r\n \"type\":\"types://core/System.Exception\"\r\n },\r\n \"info\":{\r\n \"type\":\"string\"\r\n }\r\n },\r\n \"title\":\"SystemException\"\r\n }\r\n }\r\n}","isNativeDefinition":false}]</gp:globalParameter> | ||
| <gp:globalParameter name="InnerTypes">[{"name":"Config","definition":" public class Config\r\n {\r\n /* Settings resolved at run time by this configuration Flow.\r\n Consumers in this repository read db_connection_str, to_email\r\n and basic_auth. */\r\n public string login { get; set; }\r\n public string password { get; set; }\r\n public string db_connection_str { get; set; }\r\n public string basic_auth { get; set; }\r\n public string to_email { get; set; }\r\n public string value { get; set; }\r\n public int id { get; set; }\r\n }","isNativeDefinition":true},{"name":"ErrorResponse","definition":"{\r\n \"$schema\": \"http://json-schema.org/draft-06/schema#\",\r\n \"$ref\": \"#/definitions/ErrorResponse\",\r\n \"definitions\": {\r\n \"ErrorResponse\": {\r\n \"type\": \"object\",\r\n \"additionalProperties\": true,\r\n \"properties\": {\r\n \"LevelMessage\": {\r\n \"title\": \"The Error level\",\r\n \"type\": \"string\"\r\n },\r\n \"statusCode\": {\r\n \"title\": \"The Error Status Code\",\r\n \"type\": \"integer\"\r\n },\r\n \"ErrNumber\": {\r\n \"title\": \"The Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Message\": {\r\n \"title\": \"The Error Message\",\r\n \"type\": \"string\"\r\n },\r\n \"State\": {\r\n \"title\": \"The Error State\",\r\n \"type\": \"string\"\r\n },\r\n \"HelpLink\": {\r\n \"title\": \"The Help Link\",\r\n \"type\": \"string\"\r\n },\r\n \"errNumberReason\": {\r\n \"title\": \"The initial Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Data\": {\r\n \"title\": \"The Error Data\",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"LevelMessage\": {\r\n \"title\": \"The Error level\",\r\n \"type\": \"string\"\r\n },\r\n \"statusCode\": {\r\n \"title\": \"The Error Status Code\",\r\n \"type\": \"integer\"\r\n },\r\n \"ErrNumber\": {\r\n \"title\": \"The Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Message\": {\r\n \"title\": \"The Error Message\",\r\n \"type\": \"string\"\r\n },\r\n \"State\": {\r\n \"title\": \"The Error State\",\r\n \"type\": \"string\"\r\n },\r\n \"HelpLink\": {\r\n \"title\": \"The Help Link\",\r\n \"type\": \"string\"\r\n },\r\n \"errNumberReason\": {\r\n \"title\": \"The initial Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Data\": {\r\n \"title\": \"The Data Schema\",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"LevelMessage\": {\r\n \"title\": \"The Error level\",\r\n \"type\": \"string\"\r\n },\r\n \"statusCode\": {\r\n \"title\": \"The Error Status Code\",\r\n \"type\": \"integer\"\r\n },\r\n \"ErrNumber\": {\r\n \"title\": \"The Error Number\",\r\n \"type\": \"string\"\r\n },\r\n \"Message\": {\r\n \"title\": \"The Error Message\",\r\n \"type\": \"string\"\r\n },\r\n \"State\": {\r\n \"title\": \"The Error State\",\r\n \"type\": \"string\"\r\n },\r\n \"HelpLink\": {\r\n \"title\": \"The Help Link\",\r\n \"type\": \"string\"\r\n },\r\n \"errNumberReason\": {\r\n \"title\": \"The initial Error Number\",\r\n \"type\": \"string\"\r\n }\r\n }\r\n },\r\n \"ResolveUrl\": {\r\n \"title\": \"The Resolve Url Link\",\r\n \"type\": \"string\"\r\n }\r\n }\r\n },\r\n \"ResolveUrl\": {\r\n \"title\": \"The Resolve Url Link\",\r\n \"type\": \"string\"\r\n },\r\n \"extraData\": {\r\n \"title\": \"The Error Extra Data \",\r\n \"type\": \"object\",\r\n \"properties\": {\r\n \"operationDuration\": {\r\n \"title\": \"The Operation Duration\",\r\n \"type\": \"integer\"\r\n }\r\n }\r\n }\r\n },\r\n \"title\": \"ErrorResponse\"\r\n }\r\n }\r\n}","isNativeDefinition":false},{"name":"SystemException","definition":"{\r\n \"$schema\":\"http://natec.tech/simpleschema\",\r\n \"$ref\":\"#/definitions/SystemException\",\r\n \"definitions\":{\r\n \"SystemException\":{\r\n \"type\":\"object\",\r\n \"properties\":{\r\n \"Exception\":{\r\n \"type\":\"types://core/System.Exception\"\r\n },\r\n \"info\":{\r\n \"type\":\"string\"\r\n }\r\n },\r\n \"title\":\"SystemException\"\r\n }\r\n }\r\n}","isNativeDefinition":false}]</gp:globalParameter> |
There was a problem hiding this comment.
Populate the newly declared configuration fields
When users import the shipped get-config.bpmn as the documented companion for send-links.bpmn, Activity_GetActivity still initializes only id and value, so the newly declared db_connection_str and to_email properties remain null. The consumer subsequently uses those values for its MSSQL connection and SMTP recipient, causing the example to fail at runtime even after the required companion is imported; initialize these fields with explicit placeholders that users can replace.
Useful? React with 👍 / 👎.
The repository is public, and the examples carried the addresses of a live one. Not placeholders — working hosts, an internal database address, and a key. Removed: - an API key, 54 characters, in `api-call` since 2024-03-08. Replaced with `YOUR_API_KEY`. It has been readable by anyone for two years, so treat it as disclosed and rotate it at the source; deleting it here does not remove it from the history. - two compiled assemblies, `api-call.dll` and `api-gateway.dll`. A binary in an examples repository teaches nothing and may carry more than its filename suggests. Replaced with local or neutral values: - hosts `api.wcb.kyivstar.ua`, `api.wcb-tst.kyivstar.ua`, `team-api.wcb-tst.kyivstar.ua` -> `localhost`. One of them is production, not a test rig. - the Oracle address `10.49.1.198:1521/bisdb_prm.kyivstar.ua` -> `localhost:1521/XEPDB1`, plus eight further internal addresses. - `Data Source=sqlserv;Initial Catalog=unibill` -> `Data Source=localhost;Initial Catalog=examples`; `Password=password` -> empty, so nobody inherits a credential that cannot work. - Postman collections keep the host split into segments, so the string replacement missed them; nine host arrays were rebuilt as `["localhost"]`. - the operator's name where it appeared in sample data and in a variable name. Left alone: `Natec.Workflow.*` and `natec.tech/simpleschema` are the platform's own namespace and schema, not a leak. Verified afterwards: `kyivstar`, `starlink`, `fcs`, `unibill`, `wcb` and `sqlserv` return nothing across the repository. Two PNG diagrams matched on bytes; both were opened and show a MEF.DEV architecture picture with no names in it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The group held fourteen models lifted from running systems. Read as teaching material they did not work: a newcomer met `sharepoint-get-folders-latest`, `CredentialSP`, `billCycleNo`, `AgentCard` and a node labelled "to do", and had to guess which parts were the lesson. One model was a byte-for-byte copy of the repository's own `http-stream` example. Three referenced a personal library, which the platform resolves only for the account that created it, so they could never compile for a reader. Replaced by nine models, one per group plus the configuration Flow they all share. Each is generated from the platform's own function catalogue, so no declaration can drift from the engine, and each was compiled against the platform before being committed: nine of nine, with the repository's own linter at zero findings. What changed in kind, not only in content: - The code is commented. `#Previous`, `Root.`, `Transition.Counter` and `Action.BoundaryEvents` all look like ordinary identifiers and none of them are; the comments say so at the point of use. - Every group README now states the same four things: which capabilities the example demonstrates and where to look, which types it declares and how each is used, what you actually get back, and why it is built that way. - The replies in those READMEs were taken from real runs, not written from expectation. That is how two facts got recorded that contradict the intent of the code: the error branch answers HTTP 200 with a 500 in the body, and the event example answers 204 because its second branch finishes last. - Settings point at two public sources with no key and no account — `api.frankfurter.dev` and `jsonplaceholder.typicode.com` — so the examples run without a credential to obtain. `login` and `password` stay empty. Two limits are stated in the READMEs rather than hidden. `AI/Completions` cannot be called from a model: its body reaches for `Action.BoundaryEvents` and a cancellation token that are not in scope where the engine inlines it. And a Flow that calls out needs a stand with a route to the internet; without one it ends on the error branch, which the streaming README shows as the expected reply. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The catalogue says its data is read from the files, so it was read from the files again rather than edited by hand. Forty-three models, counted by what each one actually contains. The interesting part is what the honest count now shows as uncovered. The models that were removed were the only ones using an event-based gateway, a signal and a Data Store, so all three drop to zero, and Sub Process, Multi Instance and the intermediate events drop to one. Those numbers were previously carried by material that could not be published; the gap was always there, it was just filled by something that had to go. `ExternalAction` remains uncovered, as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: faf3b70411
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "body": { | ||
| "mode": "raw", | ||
| "raw": "{\r\n \"subscriptionId\":[\r\n \"imsi-{{imsi}}\",\r\n \"msisdn-{{msisdn}}\"\r\n ],\r\n \"serviceRating\":[\r\n {\r\n \"userInformation\":{\r\n \"servedPei\":\"imei-{{imei}}\"\r\n },\r\n \"serviceInformation\":{\r\n \"userLocationinfo\":{\r\n \"utraLocation\":{\r\n \"sai\":{\r\n \"sac\":\"acf4\",\r\n \"plmnId\":{\r\n \"mnc\":\"{{mnc}}\",\r\n \"mcc\":\"{{mcc}}\"\r\n },\r\n \"lac\":\"6a33\"\r\n }\r\n }\r\n },\r\n \"sgsnMccMnc\":{\r\n \"mnc\":\"{{mnc}}\",\r\n \"mcc\":\"{{mcc}}\"\r\n },\r\n \"ratType\":\"UTRAN\",\r\n \"pdpAddress\":\"localhost\",\r\n \"chargingCharacteristics\":\"{{schar}}\",\r\n \"apn\":\"{{apn}}\"\r\n },\r\n \"serviceContextId\":\"32251@3gpp.org\",\r\n \"requestSubType\":\"DEBIT\",\r\n \"consumedUnit\":{\r\n \"TotalVolume\":10000\r\n },\r\n \"ratingGroup\":{{rg}}\r\n },\r\n {\r\n \"userInformation\":{\r\n \"servedPei\":\"imei-{{imei}}\"\r\n },\r\n \"serviceInformation\":{\r\n \"userLocationinfo\":{\r\n \"utraLocation\":{\r\n \"sai\":{\r\n \"sac\":\"acf4\",\r\n \"plmnId\":{\r\n \"mnc\":\"{{mnc}}\",\r\n \"mcc\":\"{{mcc}}\"\r\n },\r\n \"lac\":\"6a33\"\r\n }\r\n }\r\n },\r\n \"sgsnMccMnc\":{\r\n \"mnc\":\"{{mnc}}\",\r\n \"mcc\":\"{{mcc}}\"\r\n },\r\n \"ratType\":\"UTRAN\",\r\n \"pdpAddress\":\"localhost\",\r\n \"chargingCharacteristics\":\"{{schar}}\",\r\n \"apn\":\"{{apn}}\"\r\n },\r\n \"serviceContextId\":\"32251@3gpp.org\",\r\n \"requestSubType\":\"RESERVE\",\r\n \"ratingGroup\":{{rg}}\r\n }\r\n ],\r\n \"nfConsumerIdentification\":{\r\n \"nodeFunctionality\":\"OCF\"\r\n },\r\n \"invocationTimeStamp\":\"{{NOW}}\",\r\n \"invocationSequenceNumber\":2\r\n}\r\n ", |
There was a problem hiding this comment.
Keep
pdpAddress values as valid IP literals
When this Postman request is sent after configuring {{API}}, the payload now supplies "localhost" for pdpAddress; however, the repository's 3GPP-Rf_Rating-v1.1.5.yaml defines that property as an IPv4 or IPv6 string. A schema-validating rating endpoint will therefore reject the request before exercising the intended operation. Use a reserved documentation address such as 192.0.2.1 when anonymizing this field, and update the other newly changed pdpAddress occurrences likewise.
Useful? React with 👍 / 👎.
| - Проміжна подія-перехоплювач — 2 | ||
| - таймер — 1 | ||
|
|
||
| | `TMF620_Product_Catalog_Management/TMF620_Get_ProductOffering.bpmn` | Exclusive gateway; error; Data Object; Native (C# class); Inner (JSON Schema) | Action | `#Previous`, `#PreviousData`, `Input`, `Logger`, `Parameters`, `WorkflowEnvironment`, `ServiceProvider`, `PassingResult` | |
There was a problem hiding this comment.
Include parallel gateways in per-model capabilities
Add Parallel gateway to this model's capability cell: TMF620_Get_ProductOffering.bpmn contains four <parallelGateway> elements (beginning at line 93), but the rebuilt catalogue reports only its exclusive gateway. The same omission affects the other models behind the coverage table's count of 12, so readers cannot use the detailed Models section to find the capability even though the catalogue says its data comes from the files.
Useful? React with 👍 / 👎.
Two things were wrong and neither showed up in a compile. **The diagrams were unreadable.** The generator places nodes left to right and puts both data elements at the same point, so `DO_Input` and `DO_Output` sat on top of each other in every model. Every diagram is now laid out top to bottom: the main path in one column, each branch leaving a boundary event in a column of its own to the right, data elements to the left. A Sub Process keeps its own plane. Checked per plane, ignoring the boundary event that correctly sits on its task's border: zero overlaps, down from thirteen. **Two examples do not run, and the READMEs said otherwise.** Every model was started, not only compiled, and the replies recorded from the runs: - `raise-event` fails with a `NullReferenceException` inside `TransitionBoundaryEvent.Raise`. The engine reads a conveyor branch from an `AsyncLocal` that nothing ever assigns — the two lines that would are commented out at `WorkflowItemTaskCodeAction.cs:101-103`. So `Action.BoundaryEvents[…].Raise(…)` cannot work in this build at all, from any diagram. The model is correct and is kept; its README now shows the failure, the engine source, and what it will answer once that value is set again. - `stream-response` was described as failing only for want of network access. That is one of two reasons: passing chunks out uses the same `Raise`, so it would fail even on a stand that can reach the endpoint. The earlier README claimed `raise-event` answered 204 because its second branch finished last. That reading came from the HTTP status alone; the run state says `Error`. Recorded properly this time, with the run output rather than the transport code. The group index now carries the full verification table — every model, its input, and what it actually returned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b79ed38b26
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Import `service-config.bpmn` into a tenant library as `flow-patterns-config` and | ||
| compile it. Then import `use-config.bpmn` and compile that. |
There was a problem hiding this comment.
Specify the required tenant library name
When a reader follows these standalone run instructions and imports the companion into a tenant library not named tenant_shared, use-config.bpmn cannot compile because its UsedLibs and Call Activity URI hard-code tenant/tenant_shared/flow-patterns-config. The root README mentions changing that segment, but this group page and the other per-example run sections instruct users to choose any tenant library; either require the tenant_shared library here or tell readers to update each model reference.
Useful? React with 👍 / 👎.
…diagram The first layout pass understood one shape of branch: the one leaving a boundary event. Anything else — a second path out of a gateway, a failure handler shared by two nodes — fell through to the leftover pile and was stacked underneath everything, hundreds of pixels below the process it belongs to. Now every unplaced successor of a placed node opens its own column at its source's row, whatever kind of node the source is. Columns are generated rather than picked from a fixed list of three, so a model with several branches no longer crowds them into the last one. Coordinates only; no model content changed. Still zero overlaps per plane, the linter reports nothing, and all nine compile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 05ade5c070
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <process id="Process_structured_prompt" name="structured-prompt"> | ||
| <dataObjectReference id="DO_Input" name="PromptRequest" dataObjectRef="Do_Input" /> | ||
| <dataObject id="Do_Input" /> | ||
| <dataObjectReference id="DO_Output" name="PromptRequest" dataObjectRef="Do_Output" /> |
There was a problem hiding this comment.
Declare the prompt array as the process output
Change this output data object to ChatMessage[]: the happy-path task returns List<ChatMessage>, but the end event is associated with a data object declared as the input-only PromptRequest. Consumers inspecting or referencing the compiled Flow therefore receive the wrong output contract even though the runtime value is the two-message array documented in the README.
Useful? React with 👍 / 👎.
| <dataObject id="Do_Pages" /> | ||
| <dataObjectReference id="DO_Input" name="PageRequest" dataObjectRef="Do_Input" /> | ||
| <dataObject id="Do_Input" /> | ||
| <dataObjectReference id="DO_Output" name="PageRequest" dataObjectRef="Do_Output" /> |
There was a problem hiding this comment.
Declare the page collection as the process output
Change this output data object to PageInfo[]: after the multi-instance subprocess the model returns a collection of page descriptors, while the end event currently advertises PageRequest, which is only the request containing total. This makes the published output type disagree with both the actual result and the README's documented array.
Useful? React with 👍 / 👎.
The data element carrying the pages now says so twice: `isCollection="true"`, which is what BPMN reads and what makes a viewer draw the collection marker, and the `[]` already in its name, which is for the reader and the linter. The two go together; neither replaces the other. The README said something stronger and untrue. It claimed the brackets are what tell the engine the element carries a collection, and that dropping them makes the Sub Process run once instead of three times. That was inherited lore, and it does not survive a run: the same model was published three times — with the brackets alone, with both marks, and with `isCollection` alone — and every version returned three pages. What actually drives the iteration is `multiInstanceLoopCharacteristics` on the Sub Process, over the result it receives. The README now says that, and treats both marks as documentation of intent rather than mechanism. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c4f5d0eae
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <gp:globalParameter name="Functions">[{"name":"RestApi","initCode":"functions://default/RestApi","initParameters":[{"name":"Uri","type":"Uri","required":true,"oldName":"Uri","oldType":"Uri","defaultValue":"http://servername:port/resource"},{"name":"Method","type":"string","required":true,"oldName":"Method","oldType":"string","defaultValue":"GET"},{"name":"Login","type":"string","required":false,"oldName":"Login","oldType":"string","defaultValue":null},{"name":"Password","type":"string","required":false,"oldName":"Password","oldType":"string","defaultValue":null},{"name":"Headers","type":"StringDictionary","required":false,"oldName":"Headers","oldType":"StringDictionary","defaultValue":"{\r\n \"Content-Type\":\"application/json;charset=utf-16\",\r\n \"system\":\"204\",\r\n \"global_unique_id\":\"6a297fcb-956e-4228-8c11-017e9bacd629\"\r\n }"},{"name":"Body","type":"string","required":false,"oldName":"Body","oldType":"string","defaultValue":"{}"},{"name":"Encoding","type":"string","required":false,"oldName":"Encoding","oldType":"string","defaultValue":"utf-8"},{"name":"Timeout","type":"int","required":false,"oldName":"Timeout","oldType":"int","defaultValue":"0"},{"name":"Result","type":"HttpResponse","required":false,"oldName":"Result","oldType":"HttpResponse","defaultValue":null}],"oldName":"RestApi"},{"name":"RestApi/GET","initCode":"functions://default/RestApi/Get","initParameters":[{"name":"Uri","type":"Uri","required":true,"oldName":"Uri","oldType":"Uri","defaultValue":"http://servername:port/resource"},{"name":"Login","type":"string","required":false,"oldName":"Login","oldType":"string","defaultValue":null},{"name":"Password","type":"string","required":false,"oldName":"Password","oldType":"string","defaultValue":null},{"name":"Headers","type":"StringDictionary","required":false,"oldName":"Headers","oldType":"StringDictionary","defaultValue":"{\r\n \"Content-Type\":\"application/json;charset=utf-16\",\r\n \"system\":\"204\",\r\n \"global_unique_id\":\"6a297fcb-956e-4228-8c11-017e9bacd629\"\r\n }"},{"name":"Encoding","type":"string","required":false,"oldName":"Encoding","oldType":"string","defaultValue":"utf-8"},{"name":"Timeout","type":"int","required":false,"oldName":"Timeout","oldType":"int","defaultValue":"0"},{"name":"Result","type":"HttpResponse","required":false,"oldName":"Result","oldType":"HttpResponse","defaultValue":null}],"oldName":"RestApi/GET"},{"name":"JsonPath","initCode":"functions://default//JsonPath","initParameters":[{"name":"Response","type":"HttpResponse","required":true,"oldName":"Response","oldType":"HttpResponse","defaultValue":null},{"name":"Path","type":"string","required":false,"oldName":"Path","oldType":"string","defaultValue":"$"},{"name":"Result","type":"Json","required":false,"oldName":"Result","oldType":"Json","defaultValue":null}],"oldName":"JsonPath"},{"name":"SaveVariable","initCode":"functions://default//SaveVariable","initParameters":[{"name":"VariableName","type":"string","required":true,"oldName":"VariableName","oldType":"string","defaultValue":"varName"},{"name":"Data","type":"object","required":true,"oldName":"Data","oldType":"object","defaultValue":"#previous"}],"oldName":"SaveVariable"},{"name":"SQL/Oracle/Query","initCode":"functions://default//SQL/Oracle/Query","initParameters":[{"name":"userID","type":"string","required":true,"oldName":"userID","oldType":"string","defaultValue":null},{"name":"password","type":"string","required":false,"oldName":"password","oldType":"string","defaultValue":null},{"name":"dataSource","type":"string","required":false,"oldName":"dataSource","oldType":"string","defaultValue":null},{"name":"query","type":"string","required":false,"oldName":"query","oldType":"string","defaultValue":null},{"name":"Result","type":"Collection","required":false,"oldName":"Result","oldType":"Collection","defaultValue":null}],"oldName":"SQL/Oracle/Query"},{"name":"SQL/Oracle/Command","initCode":"functions://default//SQL/Oracle/Command","initParameters":[{"name":"userID","type":"string","required":true,"oldName":"userID","oldType":"string","defaultValue":null},{"name":"password","type":"string","required":false,"oldName":"password","oldType":"string","defaultValue":null},{"name":"dataSource","type":"string","required":false,"oldName":"dataSource","oldType":"string","defaultValue":null},{"name":"command","type":"string","required":false,"oldName":"command","oldType":"string","defaultValue":null},{"name":"Result","type":"int","required":false,"oldName":"Result","oldType":"int","defaultValue":null}],"oldName":"SQL/Oracle/Command"}]</gp:globalParameter> | ||
| <gp:globalParameter name="ExternalDefinitionLib">[]</gp:globalParameter> | ||
| <gp:globalParameter name="Parameters">[{"name":"dbConnectionString ","type":"string","initialValue":"host=192.168.25.204;port=5432;Database=catalyst_hw;User Id=postgres;password=example;"},{"name":"di","type":"DiagnoseIncident","initialValue":""},{"name":"HuaweiApiHost","type":"string","initialValue":"http://185.190.206.134:8484"},{"name":"InfosysApiHost","type":"string","initialValue":""},{"name":"llamaBearer","type":"string","initialValue":"LL-OlLPN1yRufuR3uEXRnTZkbHjBaC7NMq3o4wwobAGIJbUyeSQ13mcn0Bak3yUqwKG"},{"name":"QvantelApiHost","type":"string","initialValue":""},{"name":"textEmbeddingUrl","type":"string","initialValue":"http://192.168.25.204:5000"},{"name":"TroubleTicket","type":"Json","initialValue":""},{"name":"listOfAlarms","type":"string[]","initialValue":""}]</gp:globalParameter> | ||
| <gp:globalParameter name="Parameters">[{"name":"dbConnectionString ","type":"string","initialValue":"host=localhost;port=5432;Database=catalyst_hw;User Id=postgres;password=example;"},{"name":"di","type":"DiagnoseIncident","initialValue":""},{"name":"HuaweiApiHost","type":"string","initialValue":"http://localhost:8484"},{"name":"InfosysApiHost","type":"string","initialValue":""},{"name":"llamaBearer","type":"string","initialValue":"LL-OlLPN1yRufuR3uEXRnTZkbHjBaC7NMq3o4wwobAGIJbUyeSQ13mcn0Bak3yUqwKG"},{"name":"QvantelApiHost","type":"string","initialValue":""},{"name":"textEmbeddingUrl","type":"string","initialValue":"http://localhost:5000"},{"name":"TroubleTicket","type":"Json","initialValue":""},{"name":"listOfAlarms","type":"string[]","initialValue":""}]</gp:globalParameter> |
There was a problem hiding this comment.
Remove the remaining Llama bearer token
The sanitization rewrites the database and service hosts in this parameter bundle but leaves a credential-shaped llamaBearer value intact; Activity_0ueq4ev sends it as a bearer token to the public api.llama-api.com endpoint. Anyone with repository access can recover and potentially spend against that credential, so replace it with a placeholder and rotate/revoke the exposed token.
Useful? React with 👍 / 👎.
| <incoming>Fl_007</incoming> | ||
| <property id="Prop_Ev_Failed" name="__targetRef_placeholder" /> | ||
| <dataInputAssociation id="Dia_Ev_Failed"> | ||
| <sourceRef>DO_Output</sourceRef> |
There was a problem hiding this comment.
Declare the error response on the failing end event
When validation fails for an empty orderId, HandleException returns an ErrorResponse, but this failed end event is associated with DO_Output, which is declared as OrderRequest. The published process contract therefore describes the failure body as an order even though the documented and runtime value is the error object; give the failure branch its own ErrorResponse data object.
Useful? React with 👍 / 👎.
| <process id="Process_stream_response" name="stream-response"> | ||
| <dataObjectReference id="DO_Input" name="StreamRequest" dataObjectRef="Do_Input" /> | ||
| <dataObject id="Do_Input" /> | ||
| <dataObjectReference id="DO_Output" name="StreamRequest" dataObjectRef="Do_Output" /> |
There was a problem hiding this comment.
Remove the nonexistent stream response body
After all chunks are raised, T_Stream explicitly returns null, and the README says the chunks themselves are the result, but the successful end event still advertises StreamRequest through this output data object. API consumers and generated metadata will consequently expect a request-shaped response body that this flow never produces; model the success path as no-body output instead.
Useful? React with 👍 / 👎.
`Action.BoundaryEvents[…].Raise(…)` was described as broken outright. It is broken only on builds carrying a regression that lasted from 9 January 2026 to 2 September 2026 — the assignment of `BoundaryEvents.ConveyorBranch` was commented out in `WorkflowItemTaskCodeAction.cs` and has now been restored. A stand with the fix runs `raise-event` to `Completed`; one without it still answers `Error` with a `NullReferenceException` inside `Raise`. Both were observed today on two different stands, which is why the README now names the symptom to look for rather than declaring the capability dead. The index table keeps the two failing rows, because the stand these results were measured on has not been updated yet — but it now says that is what it is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
💡 Codex Reviewhttps://github.com/mef-dev/bpmn-examples/blob/7c6df2e0589bd810386be81a8ba043153d192243/tmforum-apis/TMF640_Service_Activation_and_Configuration/TMF640_Service_Activation.postman_collection.json#L460 The host for this request was sanitized to Changing only ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…o source
The platform already carries request and response examples into the generated
Swagger, and it pairs them by name: `StartSignalRoute.examples` is a dictionary
keyed by example name, `EndSignalRoute.exampelsVariants` is a list keyed by
`title`. A name present on one side and not the other silently produces a
request example with no matching response.
Every end event in this group now carries one named example, and the values are
what these models actually returned when run, not invented ones. Where a Flow
declares an HTTP route, the request example names match the response names
exactly.
Each process also gains a one-line English description and a link back to its
folder in this repository, so a reader who meets the model inside a generated
specification can find the source it came from.
Two details of the platform's shape, both learned the hard way:
- the key is spelled `exampelsVariants`, not `examplesVariants`;
- `value` is a JSON **string** on both sides. Passing an object fails the parse
with `Unexpected character encountered while parsing value: {`.
`producedTypeVariants` names the declared type each end event returns —
the flow's own type on success, `ErrorResponse` on the failure branch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fad4e4dc5a
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| "key": "Authorization", | ||
| "value": "Basic YXBpX3VzZXI6V2lkZWNvdXAx" |
There was a problem hiding this comment.
Remove the remaining Basic credential
This Base64 value decodes to a username/password pair and is still sent in the collection's Authorization headers whenever a user configures {{API}}; the same credential also remains throughout the modified TMF688 collection and its generated cURL descriptions. Because this change is intended to remove live-environment material from a public repository, replace every occurrence with a placeholder and rotate the exposed credential.
Useful? React with 👍 / 👎.
| </task> | ||
| <task id="T_Plan" name="plan the pages"> | ||
| <extensionElements> | ||
| <ep:elementParameter name="ElementImplementation">{"actionType": "Expression", "action": "// The page size is a setting, not a constant: it belongs in the\n// configuration Flow so every consumer agrees on it.\nvar size = Parameters.config.pageSize;\n\n// This step only plans. Building the list first, and walking it\n// second, is what lets the Sub Process run the pages in parallel.\nvar pages = new List<PageInfo>();\nfor (int start = 0; start < Input.total; start += size)\n pages.Add(new PageInfo() { number = pages.Count + 1, startIndex = start, size = size });\n\nLogger.LogInformation($\"{Input.total} rows split into {pages.Count} pages of {size}\");\nreturn pages;"}</ep:elementParameter> |
There was a problem hiding this comment.
Cap the final page at the remaining row count
When Input.total is not divisible by pageSize (including the documented total=25, pageSize=10 example), every PageInfo receives size = size, so the final descriptor incorrectly reports 10 rows rather than the remaining 5. This contradicts the documented short final page and misleads consumers that use the returned descriptors; set the per-page size to the minimum of the configured size and Input.total - start.
Useful? React with 👍 / 👎.
… per outcome Three things were missing from the routes, and all three show up in the generated specification rather than in the model. **Headers.** Every end event now declares the set every operation returns: `Accept` and `Content-Type` as `application/json;charset=utf-8`, `Accept-Language`, and `x-ms-client-request-id`. A `PATCH` operation takes `application/json-patch+json` instead; the pass reads the method from the start route and picks accordingly. **Formatting.** Example bodies were single-line strings. They are still strings — the platform requires that — but the JSON inside is indented, so the designer's example box can be read without horizontal scrolling. **One request per outcome.** Every response name carried the *same* request body, which explains nothing: three identical examples do not tell a reader what produces a timeout rather than a success. A request example is now given only where it genuinely differs, and a response with no request pair is allowed — not every outcome is caused by the input. The checker gained the rule that catches this: two example names carrying the same request body is a defect, and so is an example body that names an HTTP code other than the one its end event declares. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
💡 Codex Reviewhttps://github.com/mef-dev/bpmn-examples/blob/75e647a32e8ecde6644aa7428e43795e94ed6917/tmforum-apis/TMF640_Service_Activation_and_Configuration/TMF640_Service_Activation.postman_collection.json#L460 The collection sanitizes its service endpoints to ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
An example with an empty summary and no description tells a reader nothing about why it is there. Each request example now says what it is in one line and what comes back in another. Also corrects the configuration Flow's own description. It said settings live there "so no consuming Flow knows its environment", which describes a consequence rather than the thing; it now says it holds the settings the rest of the group reads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The platform compiles a model with overlapping shapes, arrows ending in empty
space and silently skipped nodes exactly as happily as a clean one, and the
editor says nothing. These scripts are the warning that is missing.
tools/verify.py runs every check over every example, non-zero exit
on any violation, ready for CI
tools/checks/ eleven readability rules, five rules about request
and response examples, plus edge, graph, label,
inline-size and overlap checks
tools/layout/ the transformation passes: top-to-bottom layout,
orthogonal routes, label and comment placement,
association ends, type-to-data-object binding,
Code Action argument binding
tools/platform/ fetch the generated C# for a published model, so an
engine error is read from the code it actually ran
rather than guessed from element names
Two of these earned their place the hard way. Among tasks the engine executes
only task and serviceTask; scriptTask, businessRuleTask, userTask, manualTask,
sendTask and receiveTask compile without a warning and are then skipped, so the
flow returns whatever the previous node produced and looks like it passed. And a
Code Action argument written as Input.x arrives as the literal string "Input.x";
only #Input.x and {Input.x} pass a value, and for a non-string parameter the
node dies with no error at all.
Running verify.py over the nine examples reports 27 violations of rules 2, 6
and 7 — the rules were written after the examples and have not been applied back
to them yet. Left visible on purpose rather than silenced.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c16ed86cb5
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| output = (proc.stdout or "") + (proc.stderr or "") | ||
| failures = len(VERDICT.findall(output)) | ||
| for pattern in COUNTED: | ||
| failures += sum(int(n) for n in pattern.findall(output)) | ||
| return failures, output |
There was a problem hiding this comment.
Treat checker process failures as verification failures
When any checker crashes—for example because a BPMN file is malformed—its traceback contains none of the parsed verdict strings, so failures remains zero and verify.py exits successfully. I confirmed that python tools/verify.py /tmp/bad.bpmn reports violations: 0 and exits 0 for invalid XML; incorporate proc.returncode into the result so CI cannot approve files that were never checked.
Useful? React with 👍 / 👎.
| has_input_example = any("{" in (a.findtext("{*}text") or "") for a in annotations) | ||
| print(f"\n7. Приклад входу в коментарі: {'є' if has_input_example else 'немає'}") | ||
| print(" " + ("ОК" if has_input_example else "ПОРУШЕНО")) | ||
|
|
||
| # 11 — межа процесу вже оголошує тип, а gateway його не змінює: другий такий | ||
| # самий аркуш поруч із задачею нічого не додає, лише змушує звіряти два. | ||
| from rule_redundant_dor import redundant_data_objects # noqa: E402 |
There was a problem hiding this comment.
Make the shipped examples satisfy the enforced annotation rules
When the documented no-argument command is run against this commit, all nine replacement models contain no textAnnotation elements, so these two unconditional checks alone produce 18 violations; missing association edges add another nine, and python tools/verify.py exits 1 with 27 total violations. Either add the required annotations and diagram edges to the examples or adjust the rules, otherwise the newly advertised CI command fails on the repository it is meant to validate.
Useful? React with 👍 / 👎.
| for fid, src, dst in self.flows: | ||
| if src not in self.pos or dst not in self.pos: | ||
| continue | ||
| sx, sy, sw, sh = self.pos[src] | ||
| tx, ty, tw, th = self.pos[dst] | ||
| start = (sx + sw // 2, sy + sh) | ||
| end = (tx + tw // 2, ty) | ||
| lines.append(f' <bpmndi:BPMNEdge id="Ed_{fid}" bpmnElement="{fid}">') |
There was a problem hiding this comment.
Preserve non-sequence diagram elements during relayout
When relayout.py is run on a model containing data associations or text annotations, render() emits edges only from self.flows, which contains only sequenceFlow entries, while annotations are also absent from the supported node tags. The semantic XML survives but its association edges and annotation shapes disappear from the regenerated diagram; I reproduced this with TMF640_Patch_Service.bpmn. Preserve or regenerate those shapes and edges before replacing the entire BPMNDiagram section.
Useful? React with 👍 / 👎.
It shipped with one model's comments baked into it — a JSON example and three paragraphs keyed by annotation id — so running it on any other model silently replaced that model's comments with those. A pass that rewrites content is not a layout pass. It now reads each textAnnotation, re-wraps prose to the requested width, leaves a structured block (JSON, lists) with its own line breaks because there every line carries meaning, and fits the frame to the result. What the comment says stays the model's business. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
💡 Codex Reviewhttps://github.com/mef-dev/bpmn-examples/blob/7e736565a904ba7b8bdaf49565871d02b95e6f0f/tmforum-apis/TMF640_Service_Activation_and_Configuration/TMF640_Service_Activation.postman_collection.json#L460 This value decodes to the username/password pair bpmn-examples/tools/layout/drop_redundant_dor.py Lines 108 to 112 in 7e73656 When a task and its downstream end event share the same data object reference, the redundancy detector marks the task association as removable, but this unconditional deletion removes the shared reference and underlying bpmn-examples/tools/checks/check_graph.py Lines 36 to 43 in 7e73656 When the semantic bpmn-examples/tools/layout/straighten.py Lines 104 to 110 in 7e73656 When ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
…side it A model nobody can regenerate can only be edited by hand, and that is how the file and the intent drift apart. Each example now carries <name>.spec.json: what it takes in, what each step does and why, what it answers with, and the types it needs. The model is what the tools make of that. python tools/build.py rebuilds all nine python tools/verify.py checks without rebuilding All nine were regenerated this way. verify: 0 violations. Compiled against the platform: 9/9. Four passes are new. split_shared_data gives each end event its own data element, so success and failure no longer share one and their arrows no longer cross. add_types carries the types, external types and libraries a step needs beyond its own input and output. add_examples writes the process documentation with the link back to source and the response example on each end event. add_notes places the comments and the input example the specification declares. snap_associations now draws an association that has no edge at all - until now a data element could sit on the diagram with nothing leading to it - routes it orthogonally, and treats captions and already-drawn lines as obstacles. place_data_labels no longer dodges lines: the caption is anchored under its own shape and the lines route around it. Two specifications sit in flow-patterns/parked with no model. They wait on the platform: AI/Completions callable from a model, IO/Local/Archive exposed to flows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58073fc654
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| </task> | ||
| <task id="T_Work" name="do the work in parts"> | ||
| <extensionElements> | ||
| <ep:elementParameter name="ElementImplementation">{"actionType": "Expression", "action": "// A long step does not have to stay silent until it ends. Raising the\n// boundary event lets a second branch report progress while this one\n// keeps working — the event is non-interrupting.\nfor (int part = 1; part <= 3; part++)\n{\n Logger.LogInformation($\"part {part} done\");\n\n // The name in brackets is the id of the boundary event on the\n // diagram. Get it wrong and the engine raises BoundaryEventNotFound.\n Action.BoundaryEvents[\"Event_Progress\"].Raise($\"part {part} of 3\");\n}\nreturn new JobRequest() { jobId = Input.jobId };"}</ep:elementParameter> |
There was a problem hiding this comment.
Add the boundary event targeted by the progress raiser
Every run that reaches T_Work attempts to raise Event_Progress, but the model declares only the unrelated Ev_Err_T_ParseConfig boundary event and contains no reporting branch. Consequently the first loop iteration cannot emit progress and instead hits the missing-boundary failure described by this example's own README; add the non-interrupting Event_Progress boundary event and its T_Report route.
Useful? React with 👍 / 👎.
| </task> | ||
| <task id="T_Stream" name="read the stream line by line"> | ||
| <extensionElements> | ||
| <ep:elementParameter name="ElementImplementation">{"actionType": "Expression", "action": "// #Previous.Reader is the open response body. Reading it line by line\n// keeps memory flat no matter how long the answer turns out to be.\nstring line;\nwhile ((line = #Previous.Reader.ReadLine()) != null)\n{\n if (string.IsNullOrWhiteSpace(line))\n continue;\n\n // Each line leaves through the boundary event, so the caller sees\n // the answer arriving instead of waiting for all of it.\n Action.BoundaryEvents[\"Event_Chunk\"].Raise(line);\n}\n\n// The stream itself is the result; there is nothing left to return.\nreturn null;"}</ep:elementParameter> |
There was a problem hiding this comment.
Add the boundary event that delivers stream chunks
When the upstream endpoint returns any nonblank line, T_Stream raises Event_Chunk, but no such boundary event or chunk-handling branch exists anywhere in this model (its only boundaries handle errors from config parsing and T_Call). Thus a reachable endpoint makes the advertised streaming path fail on the first chunk rather than forwarding it; add the non-interrupting event and delivery branch referenced by the code.
Useful? React with 👍 / 👎.
| <sequenceFlow id="Fl_001" sourceRef="Ev_Start" targetRef="CA_Config" /> | ||
| <sequenceFlow id="Fl_002" sourceRef="CA_Config" targetRef="T_ParseConfig" /> | ||
| <sequenceFlow id="Fl_003" sourceRef="T_ParseConfig" targetRef="T_Plan" /> | ||
| <sequenceFlow id="Fl_004" sourceRef="T_Plan" targetRef="Ev_End" /> |
There was a problem hiding this comment.
Route planned pages through the multi-instance subprocess
For every successful request, Fl_004 sends the result of T_Plan directly to Ev_End; the model contains neither a subProcess nor multiInstanceLoopCharacteristics. Therefore none of the documented per-page work runs, no page URLs are logged, and this cannot demonstrate the Sub Process/Multi Instance capability attributed to it in the README and catalogue.
Useful? React with 👍 / 👎.
| <startEvent id="Ev_Start" name=""> | ||
| <outgoing>Fl_001</outgoing> | ||
| <dataOutputAssociation id="Doa_Input"> | ||
| <targetRef>DO_Input</targetRef> | ||
| </dataOutputAssociation> |
There was a problem hiding this comment.
Declare the advertised HTTP route on the start event
The newly added Ev_Start has only its outgoing flow and data association; there is no StartSignalRoute element parameter anywhere in the model. Publishing it therefore cannot claim the documented POST /webhook route, so the central trigger example remains startable only through the ordinary Flow endpoints until the route configuration is added.
Useful? React with 👍 / 👎.
Running each example against the platform on its own published input found three things a compiler cannot see. Two examples raised a boundary event that was not in the model at all. They compiled and failed on the first run. The event a step raises is now declared in the specification beside it and built by add_boundary_event. A REST step without Headers throws ArgumentNullException before the call is made, and an Accept carrying a charset is rejected as a malformed header. The rates source no longer answers, so the configuration points at one that does. The copy published in the tenant library still carries the old address until someone republishes it. verify: 9 models, 0 violations compile: 9/9 run: 9/9 answer with real data Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78a7b54c21
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for fid, (src, dst) in flows.items(): | ||
| for end, kind in ((src, "outgoing"), (dst, "incoming")): | ||
| el = next((e for e in root.iter() if e.get("id") == end), None) |
There was a problem hiding this comment.
Compare sequence flows with diagram edges
When a semantic sequenceFlow has no corresponding BPMNEdge, this loop verifies only its incoming/outgoing declarations and never inspects the diagram, while check_edges.py examines only edges that already exist. Removing Ed_Fl_001 from first-flow.bpmn still lets python tools/verify.py report zero violations and exit successfully, so CI can approve a diagram with an invisible process arrow; compare the semantic flow IDs against the diagram edge IDs here.
Useful? React with 👍 / 👎.
| if outcomes: | ||
| text = re.sub( | ||
| r'<ep:elementParameter name="EndSignalRoute">(.*?)</ep:elementParameter>', | ||
| fill, text, flags=re.S) |
There was a problem hiding this comment.
Create metadata for ends without EndSignalRoute
When bpmn_forge leaves the ordinary 200 end without an EndSignalRoute, this substitution visits only the existing 500 route. That is the shape of all eight new generated consumer models: each has two end events but only one route, so success outcomes such as GREETED are never written into the BPMN despite being present in the specification and advertised as response examples. Add route metadata for unmatched end events rather than only editing routes that already exist.
Useful? React with 👍 / 👎.
Сховища даних були єдиною можливістю, якої генератор не вмів, тому весь файловий клас прикладів лишався поза досяжністю. add_stores.py будує їх із блоку `stores` і привʼязує кожне до кроку, який ним користується: рушій показує кроку лише привʼязані сховища, решта компілюється і не існує. 09 - Files створює теку, пише в неї файл, пакує його і відповідає посиланням на завантаження. Перевірено на стенді: HTTP 200 і живе посилання. Три обмеження записані там, де вони болять, а не списком: `object` сховища береться дослівно, запис не створює відсутніх тек, а AddFolderToZip недосяжний, бо System.IO.Compression не входить у посилання компілятора потоків. Спробу викликати AI/Completions відкладено: її тіло вживає CT і Action.BoundaryEvents, а в контексті вузла-задачі немає ні того, ні того. README приведені до фактів: `Raise` уже працює, і там же ціна одного підйому. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 12182450be
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| elif el.get("name") == "EndSignalRoute": | ||
| titles = [v.get("title") for v in (data.get("exampelsVariants") or []) | ||
| if isinstance(v, dict) and v.get("title")] | ||
| ends.append((data.get("code"), titles, data.get("producedTypeVariants"))) |
There was a problem hiding this comment.
Count end events that lack route metadata
When an end event has no EndSignalRoute, this loop never adds it to ends, so the checker reports zero missing examples. I confirmed this on first-flow.bpmn: it contains two semantic end events but only one route, while check_examples.py prints кінцевих подій без прикладу: 0; consequently the advertised verification command cannot detect the missing success metadata in the shipped models.
Useful? React with 👍 / 👎.
| </startEvent> | ||
| <task id="T_GetConfig" name="resolve the settings"> | ||
| <extensionElements> | ||
| <ep:elementParameter name="ElementImplementation">{"actionType": "Expression", "action": "return new Config()\n{\n ratesUrl = \"https://open.er-api.com/v6\",\n listUrl = \"https://jsonplaceholder.typicode.com/posts\",\n login = \"\",\n password = \"\",\n pageSize = 10\n};"}</ep:elementParameter> |
There was a problem hiding this comment.
Return the endpoint documented by the companion flow
When users import this shipped configuration and run use-config.bpmn with the documented { "key": "EUR" }, T_UseConfig appends /latest?base=EUR to this value and returns https://open.er-api.com/v6/latest?base=EUR, not the documented/specification result https://api.frankfurter.dev/v1/latest?base=EUR. Align this setting with the companion README and success example so the teaching flow produces its promised output.
Useful? React with 👍 / 👎.
| <task id="T_Archive" name="pack it and issue a link"> | ||
| <extensionElements> | ||
| <ep:elementParameter name="ElementImplementation">{"actionType": "Expression", "action": "// AddToZip answers with the archive as a file of its own.\nLocalFile archive = DataAssociations.DS_File.GetFile().AddToZip(\"archive.zip\");\n\n// The link carries its own authorisation: whoever receives it\n// needs no session of yours to fetch the archive.\nreturn new ArchiveResult() { folder = \"flow-patterns/archive-demo\", url = archive.CreateLink() };"}</ep:elementParameter> |
There was a problem hiding this comment.
Route archive-step failures to the error outcome
When GetFile(), AddToZip(), or CreateLink() throws, this task has no attached boundary error; the only operational boundary is attached to the preceding T_Write, so it cannot catch failures here. The run therefore terminates as an engine error instead of reaching T_HandleException and returning the advertised ARCHIVE_FAILED response; T_Folder has the same gap for folder-store failures.
Useful? React with 👍 / 👎.
Три з пʼяти помилок тієї компіляції були мої:
CS0246 тип аргументу генерується без простору імен, тож зовнішній тип
оголошено під тим самим іменем, а не під коротшим псевдонімом;
CS1061 JSON не динамічний обʼєкт - зміст дістається через Cast<T> у
оголошений тип, тому додано AiChunk, AiChoice і AiDelta;
CS0266 оголошений масив стає List<> у згенерованому методі, а #Previous
приходить як object.
Останнє довелося міряти: приведення префіксом ламає розбір, бо # мусить бути
першим символом виразу, і компілятор читає його як директиву препроцесора
(CS1040). Працює форма з as.
Лишаються дві помилки з тіла самої вбудованої функції - CT і
Action.BoundaryEvents. Їх закриває PR 4758; після розгортання цей приклад і
буде його перевіркою.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Навчальні приклади BPMN для платформи MEF.DEV: десять моделей, кожна зібрана зі специфікації, що лежить поруч, і перевірена на стенді.
Склад
first-flowInput— payload виклику,#Previous— результат попереднього крокуerror-as-branch#PreviousDataservice-config,use-configpaged-fetchraise-eventstream-responsehttp-startstructured-promptarchive-and-linkВідкладені (
parked/):ask-model,archive-and-send,ai-completion— з причинами у власних специфікаціях.Контракт специфікації
Ключі верхнього рівня:
name,config,input,steps,stores,types,externalTypes,libs,outcomes,documentation,generate.Ключі кроку:
id,name,expression|function+params,note,risky,raises.Ключі сховища:
id,name,type(File,Folder,MSSQL.Procedure…),connection,object,usedBy.Інструменти
tools/build.pyзбирає модель зі специфікації:genдає каркас, далі проходи розкладки, наприкінці — перевірка.relayout,straightensplit_shared_dataadd_boundary_eventadd_storesstores, кожне привʼязане до свого крокуadd_types,add_examples,add_notesfit_notes,place_notes,place_labels,place_data_labels,snap_associationstools/verify.py— одинадцять правил читабельності і пʼять правил прикладів. Зараз: 11 моделей, 0 порушень.Крок
genживе вgraph-api-files-sync/Tools/bpmn_forge.py;build.pyзнаходить його за змінноюBPMN_FORGE. Він лишається там, бо читає каталог вбудованих функцій із вихідного коду закритого бекенду.Перевірено на стенді
Усі дев'ять прикладів скомпільовані й запущені, кожен своїм прикладом входу: HTTP 200, справжні дані.
archive-and-linkповертає живе посилання на архів.Обмеження, записані в прикладах
objectсховища даних береться дослівно: ні{Input.x}, ніInput.xтам не підставляються.LocalFolder.AddFolderToZipнедосяжний із моделі: він береCompressionLevel, аSystem.IO.Compressionне входить у посилання компілятора потоків.AI/Completionsне компілюється у вузлі-задачі: її тіло вживаєCTіAction.BoundaryEvents, а тип параметраMessagesне резолвиться.Передумова
Спершу імпортувати
03-config-as-flow/service-config.bpmnу tenant-бібліотеку під іменемflow-patterns-configі скомпілювати. Решта моделей резолвитьactivities://bpmn-mnemo/tenant/<бібліотека>/flow-patterns-config/#latest.Пов'язане
graph-api-files-sync/Tools/BPMN-FORGE.md— описgen, правилBF-*і меж інструментаNatec.Workflow.Core/Services/BuiltinFunctions/BuiltinFunctionsProvider.cs— каталог вбудованих функцій, проти якого звіряються приклади